Merge tracemonkey to mozilla-central. a=blockers

This commit is contained in:
Robert Sayre 2010-08-28 10:50:34 -04:00
commit d91fb6ccdc
95 changed files with 2509 additions and 730 deletions

View File

@ -216,6 +216,7 @@ var TestPilotXulWindow = {
},
onUnload: function() {
document.getElementById("settings-pane").writePreferences(true);
Observers.remove("testpilot:task:changed", this._onTaskStatusChanged, this);
},

View File

@ -175,6 +175,15 @@ var TestPilotMenuUtils;
return;
}
let firefoxnav = window.document.getElementById("nav-bar");
/* This is sometimes called for windows that don't have a navbar - in
* that case, do nothing. */
if (!firefoxnav) {
return;
}
// TODO if the user has removed the feedback button via customization
// interface, we don't want to add it back in. Use a pref to store whether
// this setup was done or not.
let curSet = firefoxnav.currentSet;
if (-1 == curSet.indexOf("feedback-menu-button")) {

View File

@ -4,7 +4,7 @@
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>testpilot@labs.mozilla.com</em:id>
<em:version>1.0.2</em:version>
<em:version>1.0.3</em:version>
<em:type>2</em:type>
<!-- Target Application this extension can install into,
@ -13,7 +13,7 @@
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>3.5</em:minVersion>
<em:maxVersion>4.0b4</em:maxVersion>
<em:maxVersion>4.0b5</em:maxVersion>
</Description>
</em:targetApplication>

View File

@ -682,8 +682,6 @@ const gXPInstallObserver = {
if (!enabled) {
notificationID = "xpinstall-disabled"
if (PopupNotifications.getNotification(notificationID, browser))
return;
if (gPrefService.prefIsLocked("xpinstall.enabled")) {
messageString = gNavigatorBundle.getString("xpinstallDisabledMessageLocked");
@ -702,9 +700,6 @@ const gXPInstallObserver = {
}
}
else {
if (PopupNotifications.getNotification(notificationID, browser))
return;
messageString = gNavigatorBundle.getFormattedString("xpinstallPromptWarning",
[brandShortName, installInfo.originatingURI.host]);
@ -749,10 +744,6 @@ const gXPInstallObserver = {
});
break;
case "addon-install-complete":
var notification = PopupNotifications.getNotification(notificationID, browser);
if (notification)
PopupNotifications.remove(notification);
var needsRestart = installInfo.installs.some(function(i) {
return i.addon.pendingOperations != AddonManager.PENDING_NONE;
});

View File

@ -59,7 +59,7 @@ function test_blocked_install() {
// Wait for the blocked notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-blocked", "Should have seen the install blocked");
is(notification.id, "addon-install-blocked-notification", "Should have seen the install blocked");
is(notification.button.label, "Allow", "Should have seen the right button");
is(notification.getAttribute("label"),
gApp + " prevented this site (example.com) from asking you to install " +
@ -76,7 +76,7 @@ function test_blocked_install() {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete", "Should have seen the install complete");
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
@ -111,7 +111,7 @@ function test_whitelisted_install() {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete", "Should have seen the install complete");
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
@ -142,7 +142,7 @@ function test_failed_download() {
// Wait for the failed notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed", "Should have seen the install fail");
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"The add-on could not be downloaded because of a connection failure " +
"on example.com.",
@ -167,7 +167,7 @@ function test_corrupt_file() {
// Wait for the failed notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed", "Should have seen the install fail");
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"The add-on downloaded from example.com could not be installed " +
"because it appears to be corrupt.",
@ -192,7 +192,7 @@ function test_incompatible() {
// Wait for the failed notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed", "Should have seen the install fail");
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"XPI Test could not be installed because it is not compatible with " +
gApp + " " + gVersion + ".",
@ -221,7 +221,7 @@ function test_restartless() {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete", "Should have seen the install complete");
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Open Add-ons Manager", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test has been installed successfully.",
@ -260,7 +260,7 @@ function test_multiple() {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete", "Should have seen the install complete");
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"2 add-ons will be installed after you restart " + gApp + ".",
@ -293,7 +293,7 @@ function test_url() {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete", "Should have seen the install complete");
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
@ -321,7 +321,7 @@ function test_localfile() {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed", "Should have seen the install fail");
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"This add-on could not be installed because it appears to be corrupt.",
"Should have seen the right message");
@ -344,7 +344,7 @@ function test_wronghost() {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-failed", "Should have seen the install fail");
is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
is(notification.getAttribute("label"),
"The add-on downloaded from example.com could not be installed " +
"because it appears to be corrupt.",
@ -374,7 +374,7 @@ function test_reload() {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete", "Should have seen the install complete");
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"XPI Test will be installed after you restart " + gApp + ".",
@ -425,7 +425,7 @@ function test_theme() {
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete", "Should have seen the install complete");
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
is(notification.button.label, "Restart Now", "Should have seen the right button");
is(notification.getAttribute("label"),
"Theme Test will be installed after you restart " + gApp + ".",
@ -436,6 +436,105 @@ function test_theme() {
runNextTest();
});
});
},
function test_renotify_blocked() {
var triggers = encodeURIComponent(JSON.stringify({
"XPI": "unsigned.xpi"
}));
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
// Wait for the blocked notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-blocked-notification", "Should have seen the install blocked");
aPanel.addEventListener("popuphidden", function () {
aPanel.removeEventListener("popuphidden", arguments.callee, false);
info("Timeouts after this probably mean bug 589954 regressed");
executeSoon(function () {
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-blocked-notification",
"Should have seen the install blocked - 2nd time");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 2, "Should be two pending installs");
aInstalls[0].cancel();
aInstalls[1].cancel();
info("Closing browser tab");
gBrowser.removeTab(gBrowser.selectedTab);
runNextTest();
});
});
});
}, false);
// hide the panel (this simulates the user dismissing it)
aPanel.hidePopup();
});
},
function test_renotify_installed() {
var pm = Services.perms;
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
var triggers = encodeURIComponent(JSON.stringify({
"XPI": "unsigned.xpi"
}));
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
aWindow.document.documentElement.acceptDialog();
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
// Dismiss the notification
aPanel.addEventListener("popuphidden", function () {
aPanel.removeEventListener("popuphidden", arguments.callee, false);
// Install another
executeSoon(function () {
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
// Wait for the install confirmation dialog
wait_for_install_dialog(function(aWindow) {
aWindow.document.documentElement.acceptDialog();
info("Timeouts after this probably mean bug 589954 regressed");
// Wait for the complete notification
wait_for_notification(function(aPanel) {
let notification = aPanel.childNodes[0];
is(notification.id, "addon-install-complete-notification", "Should have seen the second install complete");
AddonManager.getAllInstalls(function(aInstalls) {
is(aInstalls.length, 2, "Should be two pending installs");
aInstalls[0].cancel();
aInstalls[1].cancel();
gBrowser.removeTab(gBrowser.selectedTab);
runNextTest();
});
});
});
});
}, false);
// hide the panel (this simulates the user dismissing it)
aPanel.hidePopup();
});
});
}
];

View File

@ -60,6 +60,7 @@ function test () {
[ 'select', false, null],
[ 'output', true, null],
[ 'fieldset', true, null],
[ 'object', 'false' ],
];
for each (let data in testData) {
@ -68,7 +69,6 @@ function test () {
let todo_testData = [
[ 'keygen', 'false' ],
[ 'object', 'false' ],
];
for each(let data in todo_testData) {

View File

@ -327,10 +327,11 @@ var tests = [
this.notification.remove();
}
},
// Test that anchor icon appears
// Test that icons appear
{ // Test #11
run: function () {
this.notifyObj = new basicNotification();
this.notifyObj.id = "geolocation";
this.notifyObj.anchorID = "geo-notification-icon";
this.notification = showNotification(this.notifyObj);
},
@ -477,8 +478,11 @@ function checkPopup(popup, notificationObj) {
is(notifications.length, 1, "only one notification displayed");
let notification = notifications[0];
let icon = document.getAnonymousElementByAttribute(notification, "class", "popup-notification-icon");
if (notificationObj.id == "geolocation")
isnot(icon.boxObject.width, 0, "icon for geo displayed");
is(notification.getAttribute("label"), notificationObj.message, "message matches");
is(notification.id, notificationObj.id, "id matches");
is(notification.id, notificationObj.id + "-notification", "id matches");
if (notificationObj.mainAction) {
is(notification.getAttribute("buttonlabel"), notificationObj.mainAction.label, "main action label matches");
is(notification.getAttribute("buttonaccesskey"), notificationObj.mainAction.accessKey, "main action accesskey matches");

View File

@ -894,8 +894,7 @@ let AboutHomeUtils = {
loadDefaultSearchEngine: function AHU_loadDefaultSearchEngine()
{
// TODO: should use originalDefaultEngine once available, see bug 587691.
let defaultEngine = Services.search.defaultEngine;
let defaultEngine = Services.search.originalDefaultEngine;
let submission = defaultEngine.getSubmission("_searchTerms_");
if (submission.postData)
throw new Error("Home page does not support POST search engines.");

View File

@ -225,8 +225,7 @@ BrowserGlue.prototype = {
Services.obs.removeObserver(this, "places-shutdown");
this._isPlacesShutdownObserver = false;
}
// places-shutdown is fired on profile-before-change, but before
// Places executes the last flush and closes connection.
// places-shutdown is fired when the profile is about to disappear.
this._onProfileShutdown();
break;
case "idle":

View File

@ -47,20 +47,47 @@ const URIS = [
, "http://c.example3.com/"
];
let expirationObserver = {
observe: function observe(aSubject, aTopic, aData) {
print("Finished expiration.");
Services.obs.removeObserver(expirationObserver,
PlacesUtils.TOPIC_EXPIRATION_FINISHED);
let db = PlacesUtils.history
.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
const TOPIC_CONNECTION_CLOSED = "places-connection-closed";
let stmt = db.createStatement(
"SELECT id FROM moz_places_temp WHERE url = :page_url "
+ "UNION ALL "
+ "SELECT id FROM moz_places WHERE url = :page_url "
let EXPECTED_NOTIFICATIONS = [
"places-shutdown"
, "places-will-close-connection"
, "places-connection-closing"
, "places-sync-finished"
, "places-expiration-finished"
, "places-sync-finished"
, "places-connection-closed"
];
const UNEXPECTED_NOTIFICATIONS = [
"xpcom-shutdown"
];
const URL = "ftp://localhost/clearHistoryOnShutdown/";
let notificationIndex = 0;
let notificationsObserver = {
observe: function observe(aSubject, aTopic, aData) {
print("Received notification: " + aTopic);
// Note that some of these notifications could arrive multiple times, for
// example in case of sync, we allow that.
if (EXPECTED_NOTIFICATIONS[notificationIndex] != aTopic)
notificationIndex++;
do_check_eq(EXPECTED_NOTIFICATIONS[notificationIndex], aTopic);
if (aTopic != TOPIC_CONNECTION_CLOSED)
return;
getDistinctNotifications().forEach(
function (topic) Services.obs.removeObserver(notificationsObserver, topic)
);
print("Looking for uncleared stuff.");
let stmt = DBConn().createStatement(
"SELECT id FROM moz_places WHERE url = :page_url "
);
try {
@ -73,6 +100,9 @@ let expirationObserver = {
stmt.finalize();
}
// Check cache.
do_check_false(cacheExists(URL));
do_test_finished();
}
}
@ -104,11 +134,60 @@ function run_test() {
PlacesUtils.history.TRANSITION_TYPED,
false, 0);
});
print("Add cache.");
storeCache(URL, "testData");
print("Wait expiration.");
Services.obs.addObserver(expirationObserver,
PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
print("Simulate shutdown.");
PlacesUtils.history.QueryInterface(Ci.nsIObserver)
.observe(null, TOPIC_GLOBAL_SHUTDOWN, null);
print("Simulate and wait shutdown.");
getDistinctNotifications().forEach(
function (topic)
Services.obs.addObserver(notificationsObserver, topic, false)
);
shutdownPlaces();
}
function getDistinctNotifications() {
let ar = EXPECTED_NOTIFICATIONS.concat(UNEXPECTED_NOTIFICATIONS);
return [ar[i] for (i in ar) if (ar.slice(0, i).indexOf(ar[i]) == -1)];
}
function storeCache(aURL, aContent) {
let cache = Cc["@mozilla.org/network/cache-service;1"].
getService(Ci.nsICacheService);
let session = cache.createSession("FTP", Ci.nsICache.STORE_ANYWHERE,
Ci.nsICache.STREAM_BASED);
let cacheEntry =
session.openCacheEntry(aURL, Ci.nsICache.ACCESS_READ_WRITE, false);
cacheEntry.setMetaDataElement("servertype", "0");
var oStream = cacheEntry.openOutputStream(0);
var written = oStream.write(aContent, aContent.length);
if (written != aContent.length) {
do_throw("oStream.write has not written all data!\n" +
" Expected: " + written + "\n" +
" Actual: " + aContent.length + "\n");
}
oStream.close();
cacheEntry.close();
}
function cacheExists(aURL) {
let cache = Cc["@mozilla.org/network/cache-service;1"].
getService(Ci.nsICacheService);
let session = cache.createSession("FTP", Ci.nsICache.STORE_ANYWHERE,
Ci.nsICache.STREAM_BASED);
try {
let cacheEntry =
session.openCacheEntry(aURL, Ci.nsICache.ACCESS_READ, true);
} catch (e) {
if (e.result == Cr.NS_ERROR_CACHE_KEY_NOT_FOUND ||
e.result == Cr.NS_ERROR_FAILURE)
return false;
// Throw the textual error description.
do_throw(e);
}
cacheEntry.close();
return true;
}

View File

@ -68,6 +68,9 @@
<preference id="general.autoScroll" name="general.autoScroll" type="bool"/>
<preference id="general.smoothScroll" name="general.smoothScroll" type="bool"/>
#ifdef XP_WIN
<preference id="gfx.direct2d.disabled" name="gfx.direct2d.disabled" type="bool" inverted="true"/>
#endif
<preference id="layout.spellcheckDefault" name="layout.spellcheckDefault" type="int"/>
#ifdef HAVE_SHELL_SERVICE
@ -174,6 +177,12 @@
label="&useSmoothScrolling.label;"
accesskey="&useSmoothScrolling.accesskey;"
preference="general.smoothScroll"/>
#ifdef XP_WIN
<checkbox id="allowHWAccel"
label="&allowHWAccel.label;"
accesskey="&allowHWAccel.accesskey;"
preference="gfx.direct2d.disabled"/>
#endif
<checkbox id="checkSpelling"
label="&checkSpelling.label;"
accesskey="&checkSpelling.accesskey;"

View File

@ -16,7 +16,6 @@
!define WindowClass "FirefoxMessageWindow"
!define DDEApplication "Firefox"
!define AppRegName "Firefox"
!define MinSupportedVer "Microsoft Windows 2000"
!define BrandShortName "@MOZ_APP_DISPLAYNAME@"
!define PreReleaseSuffix "@PRE_RELEASE_SUFFIX@"
@ -38,3 +37,14 @@
!if "@PRE_RELEASE_SUFFIX@" != ""
!define NO_INSTDIR_FROM_REG
!endif
# ARCH is used when it is necessary to differentiate the x64 registry keys from
# the x86 registry keys (e.g. the uninstall registry key).
#ifdef HAVE_64BIT_OS
!define HAVE_64BIT_OS
!define ARCH "x64"
!define MinSupportedVer "Microsoft Windows Vista x64"
#else
!define ARCH "x86"
!define MinSupportedVer "Microsoft Windows 2000"
#endif

View File

@ -134,8 +134,11 @@ VIAddVersionKey "OriginalFilename" "setup.exe"
Name "${BrandFullName}"
OutFile "setup.exe"
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
InstallDir "$PROGRAMFILES\${BrandFullName}\"
!ifdef HAVE_64BIT_OS
InstallDir "$PROGRAMFILES64\${BrandFullName}\"
!else
InstallDir "$PROGRAMFILES32\${BrandFullName}\"
!endif
ShowInstDetails nevershow
################################################################################
@ -248,7 +251,7 @@ Section "-Application" APP_IDX
; registered. bug 338878
${LogHeader} "DLL Registration"
ClearErrors
RegDLL "$INSTDIR\AccessibleMarshal.dll"
${RegisterDLL} "$INSTDIR\AccessibleMarshal.dll"
${If} ${Errors}
${LogMsg} "** ERROR Registering: $INSTDIR\AccessibleMarshal.dll **"
${Else}
@ -551,7 +554,7 @@ Function CustomAbort
${Else}
UAC::ExecCodeSegment $0
${EndIf}
CustomAbort_finish:
Return
${EndUnless}
@ -1002,8 +1005,7 @@ Function .onInit
; There must always be a core directory.
${GetSize} "$EXEDIR\core\" "/S=0K" $R5 $R7 $R8
IntOp $R8 $R5 + $R6
SectionSetSize ${APP_IDX} $R8
SectionSetSize ${APP_IDX} $R5
; Initialize $hHeaderBitmap to prevent redundant changing of the bitmap if
; the user clicks the back button

View File

@ -289,7 +289,7 @@
WriteRegStr HKLM "$0\Capabilities" "ApplicationIcon" "$8,0"
WriteRegStr HKLM "$0\Capabilities" "ApplicationName" "${BrandShortName}"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".htm" "FirefoxHTML"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".htm" "FirefoxHTML"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".html" "FirefoxHTML"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".shtml" "FirefoxHTML"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".xht" "FirefoxHTML"
@ -331,7 +331,7 @@
${WriteRegStr2} $TmpVal "$0" "PathToExe" "$8\${FileMainEXE}" 0
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Uninstall"
${WriteRegStr2} $TmpVal "$0" "Description" "${BrandFullNameInternal} (${AppVersion})" 0
${WriteRegStr2} $TmpVal "$0" "Description" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0
StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})"
${WriteRegStr2} $TmpVal "$0" "" "${AppVersion} (${AB_CD})" 0
@ -355,7 +355,7 @@
; Add uninstall registry entries. This macro tests for write access to determine
; if the uninstall keys should be added to HKLM or HKCU.
!macro SetUninstallKeys
StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})"
StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})"
WriteRegStr HKLM "$0" "${BrandShortName}InstallerTest" "Write Test"
${If} ${Errors}
@ -370,10 +370,10 @@
${GetLongPath} "$INSTDIR" $8
; Write the uninstall registry keys
${WriteRegStr2} $1 "$0" "Comments" "${BrandFullNameInternal}" 0
${WriteRegStr2} $1 "$0" "Comments" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0
${WriteRegStr2} $1 "$0" "DisplayIcon" "$8\${FileMainEXE},0" 0
${WriteRegStr2} $1 "$0" "DisplayName" "${BrandFullNameInternal} (${AppVersion})" 0
${WriteRegStr2} $1 "$0" "DisplayVersion" "${AppVersion} (${AB_CD})" 0
${WriteRegStr2} $1 "$0" "DisplayName" "${BrandFullNameInternal} ${AppVersion} (${ARCH} ${AB_CD})" 0
${WriteRegStr2} $1 "$0" "DisplayVersion" "${AppVersion}" 0
${WriteRegStr2} $1 "$0" "InstallLocation" "$8" 0
${WriteRegStr2} $1 "$0" "Publisher" "Mozilla" 0
${WriteRegStr2} $1 "$0" "UninstallString" "$8\uninstall\helper.exe" 0
@ -382,6 +382,9 @@
${WriteRegDWORD2} $1 "$0" "NoModify" 1 0
${WriteRegDWORD2} $1 "$0" "NoRepair" 1 0
${GetSize} "$8" "/S=0K" $R2 $R3 $R4
${WriteRegDWORD2} $1 "$0" "EstimatedSize" $R2 0
${If} "$TmpVal" == "HKLM"
SetShellVarContext all ; Set SHCTX to all users (e.g. HKLM)
${Else}

View File

@ -70,6 +70,7 @@ Var TmpVal
!include WinVer.nsh
!include WordFunc.nsh
!insertmacro GetSize
!insertmacro StrFilter
!insertmacro WordReplace
@ -133,11 +134,15 @@ VIAddVersionKey "OriginalFilename" "helper.exe"
!insertmacro UninstallOnInitCommon
!insertmacro un.OnEndCommon
!insertmacro un.UninstallUnOnInitCommon
Name "${BrandFullName}"
OutFile "helper.exe"
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})" "InstallLocation"
InstallDir "$PROGRAMFILES\${BrandFullName}"
!ifdef HAVE_64BIT_OS
InstallDir "$PROGRAMFILES64\${BrandFullName}\"
!else
InstallDir "$PROGRAMFILES32\${BrandFullName}\"
!endif
ShowUnInstDetails nevershow
################################################################################
@ -209,7 +214,7 @@ Section "Uninstall"
${If} ${Errors}
; If the user closed the application it can take several seconds for it to
; shut down completely. If the application is being used by another user we
; can still delete the files when the system is restarted.
; can still delete the files when the system is restarted.
Sleep 5000
${DeleteFile} "$INSTDIR\${FileMainEXE}"
ClearErrors
@ -571,18 +576,9 @@ Function .onInit
FunctionEnd
Function un.onInit
${un.GetParent} "$INSTDIR" $INSTDIR
${un.GetLongPath} "$INSTDIR" $INSTDIR
${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
Abort
${EndUnless}
StrCpy $LANGUAGE 0
${un.SetBrandNameVars} "$INSTDIR\distribution\setup.ini"
; Initialize $hHeaderBitmap to prevent redundant changing of the bitmap if
; the user clicks the back button
StrCpy $hHeaderBitmap ""
${un.UninstallUnOnInitCommon}
!insertmacro InitInstallOptionsFile "unconfirm.ini"
FunctionEnd

View File

@ -17,6 +17,8 @@
<!ENTITY useAutoScroll.accesskey "a">
<!ENTITY useSmoothScrolling.label "Use smooth scrolling">
<!ENTITY useSmoothScrolling.accesskey "m">
<!ENTITY allowHWAccel.label "Use hardware acceleration when available">
<!ENTITY allowHWAccel.accesskey "h">
<!ENTITY checkSpelling.label "Check my spelling as I type">
<!ENTITY checkSpelling.accesskey "t">

View File

@ -1236,7 +1236,7 @@ statusbarpanel#statusbar-display {
}
.tabbrowser-tab[pinned] > .tab-icon-image {
margin: 2px 0 0;
margin: 2px 2px 0;
}
.tabbrowser-tab[busy] > .tab-icon-image {

View File

@ -1391,10 +1391,12 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
height: 16px;
list-style-image: url("chrome://global/skin/icons/folder-item.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
-moz-margin-end: 3px;
}
.tabbrowser-tab:not([pinned]) > .tab-icon-image {
-moz-margin-end: 3px;
.tabbrowser-tab[pinned] > .tab-icon-image {
-moz-margin-start: 2px;
-moz-margin-end: 2px;
}
/* tabbrowser-tab focus ring */

View File

@ -52,6 +52,7 @@ MOZ_APP_NAME = @MOZ_APP_NAME@
MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@
MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
MOZ_APP_VERSION = @MOZ_APP_VERSION@
MOZ_UA_FIREFOX_VERSION = @FIREFOX_VERSION@
MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@

View File

@ -8771,7 +8771,8 @@ AC_DEFINE_UNQUOTED(MOZ_APP_UA_NAME, "$MOZ_APP_UA_NAME")
AC_SUBST(MOZ_APP_UA_NAME)
AC_DEFINE_UNQUOTED(MOZ_APP_VERSION, "$MOZ_APP_VERSION")
AC_SUBST(MOZ_APP_VERSION)
AC_DEFINE_UNQUOTED(FIREFOX_VERSION, "$FIREFOX_VERSION")
AC_DEFINE_UNQUOTED(MOZ_UA_FIREFOX_VERSION, "$FIREFOX_VERSION")
AC_SUBST(MOZ_UA_FIREFOX_VERSION)
AC_SUBST(FIREFOX_VERSION)
AC_SUBST(MOZ_PKG_SPECIAL)

View File

@ -1698,6 +1698,20 @@ nsContentSink::ContinueInterruptedParsingAsync()
NS_DispatchToCurrentThread(ev);
}
/* static */
void
nsContentSink::NotifyDocElementCreated(nsIDocument* aDoc)
{
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
observerService->
NotifyObservers(domDoc, "document-element-inserted",
EmptyString().get());
}
}
// URIs: action, href, src, longdesc, usemap, cite
PRBool
IsAttrURI(nsIAtom *aName)

View File

@ -270,6 +270,9 @@ protected:
// stylesheets are all done loading.
public:
void StartLayout(PRBool aIgnorePendingSheets);
static void NotifyDocElementCreated(nsIDocument* aDoc);
protected:
void
FavorPerformanceHint(PRBool perfOverStarvation, PRUint32 starvationDelay);

View File

@ -845,7 +845,9 @@ ExternalResourceShower(nsIURI* aKey,
nsExternalResourceMap::ExternalResource* aData,
void* aClosure)
{
aData->mViewer->Show();
if (aData->mViewer) {
aData->mViewer->Show();
}
return PL_DHASH_NEXT;
}
@ -4297,7 +4299,7 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
nsCOMPtr<nsIContent> content;
PRInt32 ns = nodeInfo->NamespaceID();
NS_NewElement(getter_AddRefs(content), ns, nodeInfo.forget(), PR_FALSE);
rv = NS_NewElement(getter_AddRefs(content), ns, nodeInfo.forget(), PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(content, aReturn);

View File

@ -767,75 +767,11 @@ nsFrameLoader::ShowRemoteFrame(nsIFrameFrame* frame, nsIView* view)
return false;
}
nsIWidget* w = view->GetWidget();
if (!w) {
NS_ERROR("Our view doesn't have a widget. Totally stuffed!");
return false;
}
nsIntSize size = GetSubDocumentSize(frame->GetFrame());
#ifdef XP_WIN
HWND parentwin =
static_cast<HWND>(w->GetNativeData(NS_NATIVE_WINDOW));
if (!mRemoteBrowser->SendCreateWidget(parentwin))
return false;
#elif defined(MOZ_WIDGET_GTK2)
GdkWindow* parent_win =
static_cast<GdkWindow*>(w->GetNativeData(NS_NATIVE_WINDOW));
gpointer user_data = nsnull;
gdk_window_get_user_data(parent_win, &user_data);
MozContainer* parentMozContainer = MOZ_CONTAINER(user_data);
GtkContainer* container = GTK_CONTAINER(parentMozContainer);
// create the socket for the child and add it to our view's widget
mRemoteSocket = gtk_socket_new();
gtk_widget_set_parent_window(mRemoteSocket, parent_win);
gtk_container_add(container, mRemoteSocket);
gtk_widget_realize(mRemoteSocket);
// set the child window's size and position
GtkAllocation alloc = { 0, 0, size.width, size.height };
gtk_widget_size_allocate(mRemoteSocket, &alloc);
gtk_widget_show(mRemoteSocket);
GdkNativeWindow id = gtk_socket_get_id(GTK_SOCKET(mRemoteSocket));
if (!mRemoteBrowser->SendCreateWidget(id))
return false;
#elif defined(MOZ_WIDGET_QT)
if (getenv("USE_XEMBED_PROXY")) {
// Very bad idea to use Xembedding for IPC, but test-ipc.xul still rendering with XEmbed
QGraphicsWidget *widget = static_cast<QGraphicsWidget*>(w->GetNativeData(NS_NATIVE_WINDOW));
NS_ENSURE_TRUE(widget, false);
QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(widget);
NS_ENSURE_TRUE(proxy, false);
mRemoteSocket = new QX11EmbedContainer();
NS_ENSURE_TRUE(mRemoteSocket, false);
proxy->setWidget(mRemoteSocket);
mRemoteSocket->show();
mRemoteSocket->resize(size.width, size.height);
if (!mRemoteBrowser->SendCreateWidget(0))
return false;
} else {
// Don't create any parent/child XEmbed, because we are painting with shared memory
if (!mRemoteBrowser->SendCreateWidget(0))
return false;
}
#elif defined(ANDROID)
// Painting with shared memory
if (!mRemoteBrowser->SendCreateWidget(0))
return false;
#elif defined(XP_MACOSX)
# warning IMPLEMENT ME
#else
#error TODO for this platform
#endif
mRemoteBrowser->Move(0, 0, size.width, size.height);
mRemoteWidgetCreated = PR_TRUE;

View File

@ -17,3 +17,4 @@ load 515829-2.html
load 570566-1.html
load 571428-1.html
load 580507-1.xhtml
load 590387.html

View File

@ -50,10 +50,13 @@
#include "nsFormSubmission.h"
#include "nsIObjectFrame.h"
#include "nsIPluginInstance.h"
#include "nsIConstraintValidation.h"
class nsHTMLObjectElement : public nsGenericHTMLFormElement,
public nsObjectLoadingContent,
public nsIDOMHTMLObjectElement
public nsIDOMHTMLObjectElement,
public nsIConstraintValidation
#ifdef MOZ_SVG
, public nsIDOMGetSVGDocument
#endif
@ -127,6 +130,9 @@ public:
void StartObjectLoad() { StartObjectLoad(PR_TRUE); }
// nsIConstraintValidation
PRBool IsBarredFromConstraintValidation() const { return PR_TRUE; }
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLObjectElement,
nsGenericHTMLFormElement)
@ -201,6 +207,7 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLObjectElement)
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, imgIContainerObserver)
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIInterfaceRequestor)
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIChannelEventSink)
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIConstraintValidation)
#ifdef MOZ_SVG
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIDOMGetSVGDocument)
#endif
@ -211,6 +218,8 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLObjectElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLObjectElement)
// nsIConstraintValidation
NS_IMPL_NSICONSTRAINTVALIDATION(nsHTMLObjectElement)
NS_IMETHODIMP
nsHTMLObjectElement::GetForm(nsIDOMHTMLFormElement **aForm)

View File

@ -9,7 +9,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345624
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<style>
input, textarea, fieldset, button, select, keygen, output { background-color: rgb(0,0,0) !important; }
input, textarea, fieldset, button, select, keygen, output, object { background-color: rgb(0,0,0) !important; }
:valid { background-color: rgb(0,255,0) !important; }
:invalid { background-color: rgb(255,0,0) !important; }
</style>
@ -25,6 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=345624
<textarea id='t' oninvalid="invalidEventHandler(event);"></textarea>
<keygen id='k'></keygen>
<output id='o'></output>
<object id='obj'></object>
</div>
<pre id="test">
<script type="application/javascript">
@ -96,6 +97,10 @@ function checkDefaultPseudoClass()
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
"Nor :valid and :invalid should apply");
is(window.getComputedStyle(document.getElementById('obj'), null)
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
"Nor :valid and :invalid should apply");
todo_is(window.getComputedStyle(document.getElementById('k'), null)
.getPropertyValue('background-color'), "rgb(0, 0, 0)",
"Nor :valid and :invalid should apply");
@ -119,9 +124,10 @@ function checkDefaultPseudoClass()
function checkSpecificWillValidate()
{
// fieldset, output, keygen (TODO) and select elements
// fieldset, output, object, keygen (TODO) and select elements
ok(!document.getElementById('f').willValidate, "Fielset element should be barred from constraint validation");
ok(!document.getElementById('o').willValidate, "Output element should be barred from constraint validation");
ok(!document.getElementById('obj').willValidate, "Object element should be barred from constraint validation");
todo(!document.getElementById('k').willValidate, "Keygen element should be barred from constraint validation");
ok(document.getElementById('s').willValidate, "Select element should not be barred from constraint validation");
@ -175,7 +181,6 @@ function checkSpecificWillValidate()
is(window.getComputedStyle(t, null).getPropertyValue('background-color'),
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
// TODO: output elements are always barred from constraint validation.
// TODO: PROGRESS
// TODO: METER
}
@ -273,6 +278,7 @@ checkConstraintValidationAPIExist(document.getElementById('s'));
checkConstraintValidationAPIExist(document.getElementById('t'));
checkConstraintValidationAPIExist(document.getElementById('k'));
checkConstraintValidationAPIExist(document.getElementById('o'));
checkConstraintValidationAPIExist(document.getElementById('obj'));
checkConstraintValidationAPIDefaultValues(document.getElementById('f'));
checkConstraintValidationAPIDefaultValues(document.getElementById('i'));
@ -281,12 +287,13 @@ checkConstraintValidationAPIDefaultValues(document.getElementById('s'));
checkConstraintValidationAPIDefaultValues(document.getElementById('t'));
checkConstraintValidationAPIDefaultValues(document.getElementById('k'));
checkConstraintValidationAPIDefaultValues(document.getElementById('o'));
checkConstraintValidationAPIDefaultValues(document.getElementById('obj'));
checkDefaultPseudoClass();
checkSpecificWillValidate();
// Not checking fieldset, output and keygen
// Not checking fieldset, output, object and keygen
// because they are always barred from constraint validation.
checkCommonWillValidate(document.getElementById('i'));
checkCommonWillValidate(document.getElementById('b'));
@ -300,8 +307,9 @@ checkCustomError(document.getElementById('s'), false);
checkCustomError(document.getElementById('t'), false);
checkCustomError(document.getElementById('f'), true);
checkCustomError(document.getElementById('o'), true);
checkCustomError(document.getElementById('obj'), true);
// Not checking fieldset, output and keygen
// Not checking fieldset, output, object and keygen
// because they are always barred from constraint validation.
checkCheckValidity(document.getElementById('i'));
checkCheckValidity(document.getElementById('b'));
@ -315,6 +323,7 @@ checkValidityStateObjectAliveWithoutElement("button");
checkValidityStateObjectAliveWithoutElement("select");
checkValidityStateObjectAliveWithoutElement("textarea");
checkValidityStateObjectAliveWithoutElement("output");
checkValidityStateObjectAliveWithoutElement("object");
</script>
</pre>

View File

@ -60,9 +60,8 @@ const PRUint32 MSEC_PER_MIN = 1000 * 60;
const PRUint32 MSEC_PER_HOUR = 1000 * 60 * 60;
const PRInt32 DECIMAL_BASE = 10;
// XXX SVG/SMIL Animation use 'accessKey' whilst SMIL3 uses 'accesskey'
// We should allow both
#define ACCESSKEY_PREFIX NS_LITERAL_STRING("accessKey(")
#define ACCESSKEY_PREFIX_LC NS_LITERAL_STRING("accesskey(") // SMIL2+
#define ACCESSKEY_PREFIX_CC NS_LITERAL_STRING("accessKey(") // SVG/SMIL ANIM
#define REPEAT_PREFIX NS_LITERAL_STRING("repeat(")
#define WALLCLOCK_PREFIX NS_LITERAL_STRING("wallclock(")
@ -264,13 +263,17 @@ ParseOptionalOffset(const nsAString& aSpec, nsSMILTimeValueSpecParams& aResult)
nsresult
ParseAccessKey(const nsAString& aSpec, nsSMILTimeValueSpecParams& aResult)
{
NS_ABORT_IF_FALSE(StringBeginsWith(aSpec, ACCESSKEY_PREFIX),
NS_ABORT_IF_FALSE(StringBeginsWith(aSpec, ACCESSKEY_PREFIX_CC) ||
StringBeginsWith(aSpec, ACCESSKEY_PREFIX_LC),
"Calling ParseAccessKey on non-accesskey-type spec");
nsSMILTimeValueSpecParams result;
result.mType = nsSMILTimeValueSpecParams::ACCESSKEY;
const PRUnichar* start = aSpec.BeginReading() + ACCESSKEY_PREFIX.Length();
NS_ABORT_IF_FALSE(
ACCESSKEY_PREFIX_LC.Length() == ACCESSKEY_PREFIX_CC.Length(),
"Case variations for accesskey prefix differ in length");
const PRUnichar* start = aSpec.BeginReading() + ACCESSKEY_PREFIX_LC.Length();
const PRUnichar* end = aSpec.EndReading();
// Expecting at least <accesskey> + ')'
@ -703,7 +706,8 @@ nsSMILParserUtils::ParseTimeValueSpecParams(const nsAString& aSpec,
}
// accesskey type
else if (StringBeginsWith(spec, ACCESSKEY_PREFIX)) {
else if (StringBeginsWith(spec, ACCESSKEY_PREFIX_LC) ||
StringBeginsWith(spec, ACCESSKEY_PREFIX_CC)) {
rv = ParseAccessKey(spec, aResult);
}

View File

@ -121,6 +121,8 @@ nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec,
// Fill in the event symbol to simplify handling later
if (mParams.mType == nsSMILTimeValueSpecParams::REPEAT) {
mParams.mEventSymbol = nsGkAtoms::repeatEvent;
} else if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY) {
mParams.mEventSymbol = nsGkAtoms::keypress;
}
ResolveReferences(aContextNode);
@ -131,9 +133,7 @@ nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec,
void
nsSMILTimeValueSpec::ResolveReferences(nsIContent* aContextNode)
{
if (mParams.mType != nsSMILTimeValueSpecParams::SYNCBASE &&
mParams.mType != nsSMILTimeValueSpecParams::EVENT &&
mParams.mType != nsSMILTimeValueSpecParams::REPEAT)
if (mParams.mType != nsSMILTimeValueSpecParams::SYNCBASE && !IsEventBased())
return;
NS_ABORT_IF_FALSE(aContextNode,
@ -155,6 +155,10 @@ nsSMILTimeValueSpec::ResolveReferences(nsIContent* aContextNode)
} else if (mParams.mType == nsSMILTimeValueSpecParams::EVENT) {
Element* target = mOwner->GetTargetElement();
mReferencedElement.ResetWithElement(target);
} else if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY) {
nsIDocument* doc = aContextNode->GetCurrentDoc();
NS_ABORT_IF_FALSE(doc, "We are in the document but current doc is null");
mReferencedElement.ResetWithElement(doc->GetRootElement());
} else {
NS_ABORT_IF_FALSE(PR_FALSE, "Syncbase or repeat spec without ID");
}
@ -277,11 +281,12 @@ nsSMILTimeValueSpec::UpdateReferencedElement(Element* aFrom, Element* aTo)
case nsSMILTimeValueSpecParams::EVENT:
case nsSMILTimeValueSpecParams::REPEAT:
case nsSMILTimeValueSpecParams::ACCESSKEY:
RegisterEventListener(aTo);
break;
default:
// not a referencing-type or not yet supported
// not a referencing-type
break;
}
}
@ -319,8 +324,7 @@ nsSMILTimeValueSpec::GetTimedElement(Element* aElement)
void
nsSMILTimeValueSpec::RegisterEventListener(Element* aTarget)
{
NS_ABORT_IF_FALSE(mParams.mType == nsSMILTimeValueSpecParams::EVENT ||
mParams.mType == nsSMILTimeValueSpecParams::REPEAT,
NS_ABORT_IF_FALSE(IsEventBased(),
"Attempting to register event-listener for unexpected nsSMILTimeValueSpec"
" type");
NS_ABORT_IF_FALSE(mParams.mEventSymbol,
@ -373,7 +377,23 @@ nsSMILTimeValueSpec::GetEventListenerManager(Element* aTarget,
NS_ABORT_IF_FALSE(aSystemGroup && !*aSystemGroup,
"Bad out param for system group");
nsIEventListenerManager* elm = aTarget->GetListenerManager(PR_TRUE);
nsCOMPtr<nsPIDOMEventTarget> piTarget;
if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY) {
nsIDocument* doc = aTarget->GetCurrentDoc();
if (!doc)
return nsnull;
nsPIDOMWindow* win = doc->GetWindow();
if (!win)
return nsnull;
piTarget = do_QueryInterface(win);
} else {
piTarget = aTarget;
}
if (!piTarget)
return nsnull;
nsIEventListenerManager* elm = piTarget->GetListenerManager(PR_TRUE);
if (!elm)
return nsnull;
@ -413,9 +433,23 @@ nsSMILTimeValueSpec::HandleEvent(nsIDOMEvent* aEvent)
PRBool
nsSMILTimeValueSpec::CheckEventDetail(nsIDOMEvent *aEvent)
{
if (mParams.mType != nsSMILTimeValueSpecParams::REPEAT)
return PR_TRUE;
switch (mParams.mType)
{
case nsSMILTimeValueSpecParams::REPEAT:
return CheckRepeatEventDetail(aEvent);
case nsSMILTimeValueSpecParams::ACCESSKEY:
return CheckAccessKeyEventDetail(aEvent);
default:
// nothing to check
return PR_TRUE;
}
}
PRBool
nsSMILTimeValueSpec::CheckRepeatEventDetail(nsIDOMEvent *aEvent)
{
nsCOMPtr<nsIDOMTimeEvent> timeEvent = do_QueryInterface(aEvent);
if (!timeEvent) {
NS_WARNING("Received a repeat event that was not a DOMTimeEvent");
@ -424,7 +458,64 @@ nsSMILTimeValueSpec::CheckEventDetail(nsIDOMEvent *aEvent)
PRInt32 detail;
timeEvent->GetDetail(&detail);
return detail == mParams.mRepeatIterationOrAccessKey;
return detail > 0 && (PRUint32)detail == mParams.mRepeatIterationOrAccessKey;
}
PRBool
nsSMILTimeValueSpec::CheckAccessKeyEventDetail(nsIDOMEvent *aEvent)
{
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
if (!keyEvent) {
NS_WARNING("Received an accesskey event that was not a DOMKeyEvent");
return PR_FALSE;
}
// Ignore the key event if any modifier keys are pressed UNLESS we're matching
// on the charCode in which case we ignore the state of the shift and alt keys
// since they might be needed to generate the character in question.
PRBool isCtrl;
PRBool isMeta;
keyEvent->GetCtrlKey(&isCtrl);
keyEvent->GetMetaKey(&isMeta);
if (isCtrl || isMeta)
return PR_FALSE;
PRUint32 code;
keyEvent->GetCharCode(&code);
if (code)
return code == mParams.mRepeatIterationOrAccessKey;
// Only match on the keyCode if it corresponds to some ASCII character that
// does not produce a charCode.
// In this case we can safely bail out if either alt or shift is pressed since
// they won't already be incorporated into the keyCode unlike the charCode.
PRBool isAlt;
PRBool isShift;
keyEvent->GetAltKey(&isAlt);
keyEvent->GetShiftKey(&isShift);
if (isAlt || isShift)
return PR_FALSE;
keyEvent->GetKeyCode(&code);
switch (code)
{
case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
return mParams.mRepeatIterationOrAccessKey == 0x08;
case nsIDOMKeyEvent::DOM_VK_RETURN:
case nsIDOMKeyEvent::DOM_VK_ENTER:
return mParams.mRepeatIterationOrAccessKey == 0x0A ||
mParams.mRepeatIterationOrAccessKey == 0x0D;
case nsIDOMKeyEvent::DOM_VK_ESCAPE:
return mParams.mRepeatIterationOrAccessKey == 0x1B;
case nsIDOMKeyEvent::DOM_VK_DELETE:
return mParams.mRepeatIterationOrAccessKey == 0x7F;
default:
return PR_FALSE;
}
}
nsSMILTimeValue

View File

@ -99,6 +99,8 @@ protected:
nsIDOMEventGroup** aSystemGroup);
void HandleEvent(nsIDOMEvent* aEvent);
PRBool CheckEventDetail(nsIDOMEvent* aEvent);
PRBool CheckRepeatEventDetail(nsIDOMEvent* aEvent);
PRBool CheckAccessKeyEventDetail(nsIDOMEvent* aEvent);
nsSMILTimeValue ConvertBetweenTimeContainers(const nsSMILTimeValue& aSrcTime,
const nsSMILTimeContainer* aSrcContainer);

View File

@ -54,6 +54,7 @@ _TEST_FILES = \
smilAnimateMotionValueLists.js \
smilTestUtils.js \
smilXHR_helper.svg \
test_smilAccessKey.xhtml \
test_smilAnimateMotion.xhtml \
test_smilAnimateMotionInvalidValues.xhtml \
test_smilAnimateMotionOverrideRules.xhtml \

View File

@ -0,0 +1,360 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test for SMIL accessKey support</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=587910">Mozilla Bug
587910</a>
<p id="display"></p>
<div id="content" style="display: none">
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px">
<circle cx="20" cy="20" r="15" fill="blue" id="circle"/>
</svg>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
/** Test for SMIL accessKey support **/
const gSvgns = "http://www.w3.org/2000/svg";
var gSvg = document.getElementById("svg");
SimpleTest.waitForExplicitFinish();
function main()
{
gSvg.pauseAnimations();
// Basic syntax
testOk('accessKey(a)', 'a');
testOk(' accessKey(a) ', 'a');
testNotOk('accessKey (a)', 'a');
testNotOk('accessKey( a)', 'a');
testNotOk('accessKey(a )', 'a');
testNotOk('accessKey(a)', 'b');
testNotOk('accessKey()', ' ');
// Test the test framework itself
testOk('accessKey(a)', 97);
// Allow for either accessKey (SVG / SMIL Animation) or accesskey (SMIL2+)
testOk('accesskey(a)', 'a');
// Offset
testOk('accessKey(a)+0s', 'a');
testOk('accessKey(a) + 0min', 'a');
testOk('accessKey(a) -0h', 'a');
testOk('accessKey(a)+100ms', 'a', 0, 0.1);
testOk('accessKey(a)-0.1s', 'a', 0, -0.1);
// Id references are not allowed
testNotOk('svg.accessKey(a)', 'a');
testNotOk('window.accessKey(a)', 'a');
// Case sensitivity
testOk('accessKey(A)', 'A');
testNotOk('accessKey(a)', 'A');
testNotOk('accessKey(A)', 'a');
// Test unusual characters
testOk('accessKey(-)', '-');
testOk('accessKey(\\)', '\\');
testOk('accessKey( )', ' ');
testOk('accessKey(\x0D)', 0, 13); // Return
testOk('accessKey(\x0D)', 0, 14); // Enter
testOk('accessKey(\n)', 0, 13); // New line
testOk('accessKey(\r)', 0, 13); // Carriage return
testOk('accessKey(\x08)', 0, 8); // Backspace
testOk('accessKey(\x1B)', 0, 0x1B); // Escape
testOk('accessKey(\x7F)', 0, 46); // Del
// Check some disallowed keys
// -- For now we don't allow tab since the interaction with focus causes
// confusing results
testNotOk('accessKey(\x09)', 0, 9); // Tab
// Test setting the keyCode field
testNotOk('accessKey(a)', 0, 97);
testOk('accessKey(a)', 97, 66); // Give priority to charCode field
testNotOk('accessKey(a)', 98, 97); // Give priority to charCode field
// Test unicode
testOk("accessKey(\u20AC)", 8364); // euro-symbol
// Test an astral character just to make sure we don't crash
testOk("accessKey(\uD835\uDC00)", 119808); // mathematical bold capital A
// 0x1D400
// Test bad surrogate pairs don't confuse us either
testNotOk("accessKey(\uD800\uD800)", 97);
testNotOk("accessKey(\uD80020)", 97);
testNotOk("accessKey(\uD800)", 97);
// Test modifiers
// -- When matching on charCode ignore shift and alt
testNotOk('accessKey(a)', 'a', 0, 0, { ctrl: true });
testNotOk('accessKey(a)', 'a', 0, 0, { meta: true });
testOk('accessKey(a)', 'a', 0, 0, { alt: true });
testOk('accessKey(a)', 'a', 0, 0, { shift: true });
testNotOk('accessKey(a)', 'a', 0, 0, { shift: true, ctrl: true });
testNotOk('accessKey(a)', 'a', 0, 0, { alt: true, meta: true });
// -- When matching on keyCode ignore all
testNotOk('accessKey(\x0D)', 0, 13, 0, { ctrl: true });
testNotOk('accessKey(\x0D)', 0, 13, 0, { meta: true });
testNotOk('accessKey(\x0D)', 0, 13, 0, { alt: true });
testNotOk('accessKey(\x0D)', 0, 13, 0, { shift: true });
testNotOk('accessKey(\x0D)', 0, 13, 0, { shift: true, ctrl: true });
testOpenEnd();
testPreventDefault();
testDispatchToWindow();
testAdoptNode();
testFauxEvent();
SimpleTest.finish();
}
function testOk(spec, charCode, keyCode, offset, modifiers)
{
if (typeof offset == 'undefined') offset = 0;
var msg = "No interval created for '" + spec +
"' with input [charCode: " + charCode + "; keyCode: " + keyCode + "]" +
getModifiersDescr(modifiers);
ok(test(spec, charCode, keyCode, offset, modifiers), msg);
}
function testNotOk(spec, charCode, keyCode, offset, modifiers)
{
if (typeof offset == 'undefined') offset = 0;
var msg = "Interval unexpectedly created for '" + spec +
"' with input [charCode: " + charCode + "; keyCode: " + keyCode + "]" +
getModifiersDescr(modifiers);
ok(!test(spec, charCode, keyCode, offset, modifiers), msg);
}
function getModifiersDescr(modifiers)
{
if (typeof modifiers != 'object')
return '';
var str = ' modifiers set:';
for (var key in modifiers) {
if (modifiers[key]) str += ' ' + key;
}
return str;
}
function test(spec, charCode, keyCode, offset, modifiers)
{
gSvg.setCurrentTime(1);
ok(gSvg.animationsPaused(), "Expected animations to be paused");
var anim = createAnim(spec);
var evt = createEvent(charCode, keyCode, modifiers);
document.getElementById('circle').dispatchEvent(evt);
var gotStartTimeOk = true;
try {
var start = anim.getStartTime();
if (offset) {
var expected = gSvg.getCurrentTime() + offset;
ok(Math.abs(expected - start) <= 0.00001,
"Unexpected start time for animation with begin: " + spec +
" got " + start + ", expected " + expected);
} else {
is(start, gSvg.getCurrentTime() + offset,
"Unexpected start time for animation with begin: " + spec);
}
} catch(e) {
is(e.code, DOMException.INVALID_STATE_ERR,
"Unexpected exception code: " + e);
gotStartTimeOk = false;
}
removeElement(anim);
return gotStartTimeOk;
}
function createAnim(beginSpec)
{
var anim = document.createElementNS(gSvgns, 'animate');
anim.setAttribute('attributeName', 'cx');
anim.setAttribute('values', '0; 100');
anim.setAttribute('dur', '10s');
anim.setAttribute('begin', beginSpec);
return document.getElementById('circle').appendChild(anim);
}
function createEvent(charCode, keyCode, modifiers)
{
if (typeof charCode == 'string') {
is(charCode.length, 1,
"If charCode is a string it should be 1 character long");
charCode = charCode.charCodeAt(0);
} else if (typeof charCode == 'undefined') {
charCode = 0;
}
args = { ctrl: false, alt: false, shift: false, meta: false };
if (typeof modifiers == 'object') {
for (var key in modifiers)
args[key] = modifiers[key];
}
if (typeof keyCode == 'undefined') keyCode = 0;
var evt = document.createEvent("KeyboardEvent");
evt.initKeyEvent("keypress", true, true, window,
args['ctrl'],
args['alt'],
args['shift'],
args['meta'],
keyCode,
charCode);
return evt;
}
function testOpenEnd()
{
// Test that an end specification with an accesskey value is treated as open
// ended
gSvg.setCurrentTime(0);
ok(gSvg.animationsPaused(), "Expected animations to be paused");
var anim = createAnim('0s; 2s');
anim.setAttribute('end', '1s; accessKey(a)');
gSvg.setCurrentTime(2);
try {
is(anim.getStartTime(), 2,
"Unexpected start time for second interval of open-ended animation");
} catch(e) {
is(e.code, DOMException.INVALID_STATE_ERR,
"Unexpected exception code:" + e.code);
ok(false, "Failed to recognise accessKey as qualifying for creating an " +
"open-ended interval");
}
removeElement(anim);
}
function testPreventDefault()
{
// SVG/SMIL don't specify what should happen if preventDefault is called on
// the keypress event. For now, for consistency with event timing we ignore
// it.
gSvg.setCurrentTime(1);
ok(gSvg.animationsPaused(), "Expected animations to be paused");
var anim = createAnim('accessKey(a)');
var evt = createEvent('a');
var circle = document.getElementById('circle');
var func = function(evt) { evt.preventDefault(); }
circle.addEventListener('keypress', func, false);
circle.dispatchEvent(evt);
try {
var start = anim.getStartTime();
} catch(e) {
ok(false, "preventDefault() cancelled accessKey handling");
}
circle.removeEventListener('keypress', func, false);
removeElement(anim);
}
function testDispatchToWindow()
{
gSvg.setCurrentTime(1);
ok(gSvg.animationsPaused(), "Expected animations to be paused");
var anim = createAnim('accessKey(a)');
var evt = createEvent('a');
window.dispatchEvent(evt);
try {
var start = anim.getStartTime();
} catch(e) {
ok(false, "Key event dispatched to the window failed to trigger " +
"accesskey handling");
}
removeElement(anim);
}
function testAdoptNode()
{
gSvg.setCurrentTime(1);
ok(gSvg.animationsPaused(), "Expected animations to be paused");
// Create a new document with an animation element
var newdoc = document.implementation.createDocument(gSvgns, 'svg', null);
var anim = newdoc.createElementNS(gSvgns, 'animate');
anim.setAttribute('attributeName', 'cx');
anim.setAttribute('values', '0; 100');
anim.setAttribute('dur', '10s');
anim.setAttribute('begin', 'accesskey(a)');
newdoc.documentElement.appendChild(anim);
// Adopt
ok(anim.ownerDocument !== document,
"Expected newly created animation to belong to a different doc");
document.adoptNode(anim);
document.getElementById('circle').appendChild(anim);
ok(anim.ownerDocument === document,
"Expected newly created animation to belong to the same doc");
var evt = createEvent('a');
// Now fire an event at the original window and check nothing happens
newdoc.dispatchEvent(evt);
try {
var start = anim.getStartTime();
ok(false, "Adopted node still receiving accesskey events from old doc");
} catch(e) {
// Ok
}
// And then fire at our window
document.dispatchEvent(evt);
try {
var start = anim.getStartTime();
} catch(e) {
ok(false, "Adopted node failed to catch accesskey event");
}
removeElement(anim);
}
function testFauxEvent()
{
// Test a non-KeyEvent labelled as a key event
gSvg.setCurrentTime(0);
ok(gSvg.animationsPaused(), "Expected animations to be paused");
var anim = createAnim('accessKey(a)');
var evt = document.createEvent("SVGEvents");
evt.initEvent("keypress", true, true);
document.getElementById('circle').dispatchEvent(evt);
// We're really just testing that the above didn't crash us, but while we're
// at it, just do a sanity check that we didn't also create an interval
try {
var start = anim.getStartTime();
ok(false, "Faux event generated interval");
} catch(e) {
// All is well
}
removeElement(anim);
}
window.addEventListener("load", main, false);
]]>
</script>
</pre>
</body>
</html>

View File

@ -446,7 +446,7 @@ nsXMLContentSink::OnTransformDone(nsresult aResult,
mDocument->IndexOf(rootElement));
mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
}
// Start the layout process
StartLayout(PR_FALSE);
@ -1088,6 +1088,10 @@ nsXMLContentSink::HandleStartElement(const PRUnichar *aName,
MaybeStartLayout(PR_FALSE);
}
if (content == mDocElement) {
NotifyDocElementCreated(mDocument);
}
return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl() :
result;
}

View File

@ -54,6 +54,7 @@
#include "mozilla/dom/Element.h"
#include "nsIDOMDocumentFragment.h"
#include "nsBindingManager.h"
#include "nsIScriptSecurityManager.h"
using namespace mozilla::dom;
@ -157,20 +158,26 @@ nsXMLPrettyPrinter::PrettyPrint(nsIDocument* aDocument,
NS_ASSERTION(xblDoc, "xml document doesn't implement nsIDOMDocumentXBL");
NS_ENSURE_TRUE(xblDoc, NS_ERROR_FAILURE);
xblDoc->LoadBindingDocument(NS_LITERAL_STRING("chrome://global/content/xml/XMLPrettyPrint.xml"));
nsCOMPtr<nsIURI> bindingUri;
rv = NS_NewURI(getter_AddRefs(bindingUri),
NS_LITERAL_STRING("chrome://global/content/xml/XMLPrettyPrint.xml#prettyprint"));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> sysPrincipal;
nsContentUtils::GetSecurityManager()->
GetSystemPrincipal(getter_AddRefs(sysPrincipal));
aDocument->BindingManager()->LoadBindingDocument(aDocument, bindingUri,
sysPrincipal);
nsCOMPtr<nsIDOMElement> rootElem;
sourceDocument->GetDocumentElement(getter_AddRefs(rootElem));
NS_ENSURE_TRUE(rootElem, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIContent> rootCont = aDocument->GetRootElement();
NS_ENSURE_TRUE(rootCont, NS_ERROR_UNEXPECTED);
rv = xblDoc->AddBinding(rootElem,
NS_LITERAL_STRING("chrome://global/content/xml/XMLPrettyPrint.xml#prettyprint"));
rv = aDocument->BindingManager()->AddLayeredBinding(rootCont, bindingUri,
sysPrincipal);
NS_ENSURE_SUCCESS(rv, rv);
// Hand the result document to the binding
nsCOMPtr<nsIObserver> binding;
nsCOMPtr<nsIContent> rootCont = do_QueryInterface(rootElem);
NS_ASSERTION(rootCont, "Element doesn't implement nsIContent");
aDocument->BindingManager()->GetBindingImplementation(rootCont,
NS_GET_IID(nsIObserver),
(void**)getter_AddRefs(binding));

View File

@ -68,6 +68,7 @@
#include "nsIHTMLContentSink.h"
#include "nsContentUtils.h"
#include "txXMLUtils.h"
#include "nsContentSink.h"
#include "nsINode.h"
#include "nsContentCreatorFunctions.h"
#include "txError.h"
@ -577,13 +578,14 @@ txMozillaXMLOutput::closePrevious(PRBool aFlushText)
NS_ENSURE_SUCCESS(rv, rv);
}
if (currentIsDoc) {
mRootContentCreated = PR_TRUE;
}
rv = mCurrentNode->AppendChildTo(mOpenedElement, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
if (currentIsDoc) {
mRootContentCreated = PR_TRUE;
nsContentSink::NotifyDocElementCreated(mDocument);
}
mCurrentNode = mOpenedElement;
mOpenedElement = nsnull;
}

View File

@ -403,7 +403,7 @@ NS_IMETHODIMP nsDefaultURIFixup::KeywordToURI(const nsACString& aKeyword,
nsCOMPtr<nsIBrowserSearchService> searchSvc = do_GetService("@mozilla.org/browser/search-service;1");
if (searchSvc) {
nsCOMPtr<nsISearchEngine> defaultEngine;
searchSvc->GetDefaultEngine(getter_AddRefs(defaultEngine));
searchSvc->GetOriginalDefaultEngine(getter_AddRefs(defaultEngine));
if (defaultEngine) {
nsCOMPtr<nsISearchSubmission> submission;
// We want to allow default search plugins to specify alternate

View File

@ -3986,6 +3986,10 @@ nsGlobalWindow::SetFullScreen(PRBool aFullScreen)
if (itemType != nsIDocShellTreeItem::typeChrome)
return NS_ERROR_FAILURE;
// If we are already in full screen mode, just return.
if (mFullScreen == aFullScreen)
return NS_OK;
// dispatch a "fullscreen" DOM event so that XUL apps can
// respond visually if we are kicked into full screen mode
if (!DispatchCustomEvent("fullscreen")) {
@ -4001,12 +4005,14 @@ nsGlobalWindow::SetFullScreen(PRBool aFullScreen)
xulWin->SetIntrinsicallySized(PR_FALSE);
}
// Set this before so if widget sends an event indicating its
// gone full screen, the state trap above works.
mFullScreen = aFullScreen;
nsCOMPtr<nsIWidget> widget = GetMainWidget();
if (widget)
widget->MakeFullScreen(aFullScreen);
mFullScreen = aFullScreen;
return NS_OK;
}

View File

@ -47,7 +47,9 @@
* http://www.w3.org/TR/DOM-Level-2-HTML/
*/
[scriptable, uuid(a6cf90ac-15b3-11d2-932e-00805f8add32)]
interface nsIDOMValidityState;
[scriptable, uuid(9b93aab4-7fe8-4f79-9ad2-0623178a0c46)]
interface nsIDOMHTMLObjectElement : nsIDOMHTMLElement
{
readonly attribute nsIDOMHTMLFormElement form;
@ -70,4 +72,12 @@ interface nsIDOMHTMLObjectElement : nsIDOMHTMLElement
attribute DOMString width;
// Introduced in DOM Level 2:
readonly attribute nsIDOMDocument contentDocument;
// The following lines are parte of the constraint validation API, see:
// http://dev.w3.org/html5/spec/forms.html#the-constraint-validation-api
readonly attribute boolean willValidate;
readonly attribute nsIDOMValidityState validity;
readonly attribute DOMString validationMessage;
boolean checkValidity();
void setCustomValidity(in DOMString error);
};

View File

@ -90,7 +90,6 @@
#include "nsGeolocation.h"
#ifdef MOZ_WIDGET_QT
#include <QX11EmbedWidget>
#include <QGraphicsView>
#include <QGraphicsWidget>
#endif
@ -430,17 +429,9 @@ TabChild::RecvCreateWidget(const MagicWindowHandle& parentWidget)
}
#ifdef MOZ_WIDGET_GTK2
GtkWidget* win = gtk_plug_new((GdkNativeWindow)parentWidget);
gtk_widget_show(win);
GtkWidget* win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
#elif defined(MOZ_WIDGET_QT)
QX11EmbedWidget *embedWin = nsnull;
if (parentWidget) {
embedWin = new QX11EmbedWidget();
NS_ENSURE_TRUE(embedWin, false);
embedWin->embedInto(parentWidget);
embedWin->show();
}
QGraphicsView *view = new QGraphicsView(new QGraphicsScene(), embedWin);
QGraphicsView *view = new QGraphicsView(new QGraphicsScene());
NS_ENSURE_TRUE(view, false);
QGraphicsWidget *win = new QGraphicsWidget();
NS_ENSURE_TRUE(win, false);

View File

@ -85,7 +85,7 @@ function clickNotificationButton(aButtonIndex) {
var chromeWin = getChromeWindow();
if (chromeWin.PopupNotifications) {
var panel = chromeWin.PopupNotifications.panel;
var notificationEl = panel.getElementsByAttribute("id", "geolocation")[0];
var notificationEl = panel.getElementsByAttribute("id", "geolocation-notification")[0];
if (aButtonIndex == kAcceptButton)
notificationEl.button.doCommand();
else if (aButtonIndex == kDenyButton)

View File

@ -4,7 +4,7 @@
package="org.mozilla.@MOZ_APP_NAME@"
android:installLocation="auto"
android:versionCode="1"
android:versionName="@MOZ_APP_VERSION@"
android:versionName=@MOZ_APP_VERSION@
android:sharedUserId="org.mozilla.sharedID">
<uses-sdk android:minSdkVersion="5"
android:targetSdkVersion="5"/>

View File

@ -1,4 +1,5 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-/ * ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
@ -59,6 +60,7 @@ abstract public class GeckoApp
public static FrameLayout mainLayout;
public static GeckoSurfaceView surfaceView;
public static GeckoApp mAppContext;
ProgressDialog mProgressDialog;
void launch()
{
@ -102,6 +104,10 @@ abstract public class GeckoApp
ViewGroup.LayoutParams.FILL_PARENT));
if (!GeckoAppShell.sGeckoRunning) {
mProgressDialog =
ProgressDialog.show(GeckoApp.this, "", getAppName() +
" is loading", true);
// Load our JNI libs; we need to do this before launch() because
// setInitialSize will be called even before Gecko is actually up
// and running.

View File

@ -1,4 +1,4 @@
/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -135,12 +135,12 @@ class GeckoSurfaceView
mSurfaceLock.unlock();
}
}
public void surfaceCreated(SurfaceHolder holder) {
if (GeckoAppShell.sGeckoRunning)
mSurfaceNeedsRedraw = true;
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("GeckoAppJava", "surface destroyed");
mSurfaceValid = false;
@ -211,6 +211,10 @@ class GeckoSurfaceView
}
public void draw2D(ByteBuffer buffer) {
if (GeckoApp.mAppContext.mProgressDialog != null) {
GeckoApp.mAppContext.mProgressDialog.dismiss();
GeckoApp.mAppContext.mProgressDialog = null;
}
Canvas c = getHolder().lockCanvas();
if (c == null)
return;

View File

@ -54,7 +54,6 @@ JAVAFILES = \
DEFINES += \
-DMOZ_APP_DISPLAYNAME=$(MOZ_APP_DISPLAYNAME) \
-DMOZ_APP_NAME=$(MOZ_APP_NAME) \
-DMOZ_APP_VERSION=$(MOZ_APP_VERSION) \
-DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME)
GARBAGE += \

View File

@ -84,6 +84,8 @@
#include "mozilla/FunctionTimer.h"
#include "nsIGfxInfo.h"
gfxPlatform *gPlatform = nsnull;
// These two may point to the same profile
@ -220,6 +222,17 @@ gfxPlatform::Init()
gfxAtoms::RegisterAtoms();
/* Initialize the GfxInfo service.
* Note: we can't call functions on GfxInfo that depend
* on gPlatform until after it has been initialized
* below. GfxInfo initialization annotates our
* crash reports so we want to do it before
* we try to load any drivers and do device detection
* incase that code crashes. See bug #591561. */
nsCOMPtr<nsIGfxInfo> gfxInfo;
/* this currently will only succeed on Windows */
gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
#if defined(XP_WIN)
gPlatform = new gfxWindowsPlatform;
#elif defined(XP_MACOSX)

View File

@ -54,6 +54,7 @@
#include "nsIWindowsRegKey.h"
#include "nsILocalFile.h"
#include "plbase64.h"
#include "nsIXULRuntime.h"
#ifdef MOZ_FT2_FONTS
#include "ft2build.h"
@ -232,7 +233,17 @@ gfxWindowsPlatform::gfxWindowsPlatform()
NS_RegisterMemoryReporter(new D2DVRAMReporter());
mD2DDevice = NULL;
if (isVistaOrHigher) {
PRBool d2dDisabled = PR_FALSE;
nsresult rv = pref->GetBoolPref("gfx.direct2d.disabled", &d2dDisabled);
if (NS_FAILED(rv))
d2dDisabled = PR_FALSE;
nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
PRBool safeMode = PR_FALSE;
if (xr)
xr->GetInSafeMode(&safeMode);
if (isVistaOrHigher && !d2dDisabled && !safeMode) {
// We need a DWriteFactory to work.
HMODULE d3d10module = LoadLibraryA("d3d10_1.dll");
D3D10CreateDevice1Func createD3DDevice = (D3D10CreateDevice1Func)
@ -282,7 +293,6 @@ gfxWindowsPlatform::gfxWindowsPlatform()
#endif
#ifdef CAIRO_HAS_DWRITE_FONT
nsresult rv;
PRBool useDirectWrite = PR_FALSE;
rv = pref->GetBoolPref(
@ -315,7 +325,8 @@ gfxWindowsPlatform::gfxWindowsPlatform()
#endif
PRInt32 rmode;
if (NS_SUCCEEDED(pref->GetIntPref("mozilla.widget.render-mode", &rmode))) {
if (!safeMode &&
NS_SUCCEEDED(pref->GetIntPref("mozilla.widget.render-mode", &rmode))) {
if (rmode >= 0 && rmode < RENDER_MODE_MAX) {
#ifdef CAIRO_HAS_DWRITE_FONT
if (rmode != RENDER_DIRECT2D && !useDirectWrite) {

View File

@ -5066,6 +5066,7 @@ AC_SUBST(MOZ_APP_NAME)
AC_SUBST(MOZ_APP_DISPLAYNAME)
AC_SUBST(MOZ_APP_UA_NAME)
AC_SUBST(MOZ_APP_VERSION)
AC_SUBST(MOZ_UA_FIREFOX_VERSION)
AC_SUBST(FIREFOX_VERSION)
AC_SUBST(MOZ_PKG_SPECIAL)

View File

@ -333,4 +333,3 @@ load 586806-1.html
load 586806-2.html
load 586806-3.html
load 586973-1.html
load 590387.html

View File

@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
keypress(0x20);
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<circle id="circle" r="10"/>
<rect width="100" height="100" fill="red">
<set attributeName="fill" attributeType="CSS"
to="green" begin="accesskey(&#x20;)" dur="4s"/>
<set attributeName="width" attributeType="XML"
to="200" begin="accesskey(&#x21;)" dur="4s"/>
</rect>
</svg>

After

Width:  |  Height:  |  Size: 647 B

View File

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="
document.documentElement.pauseAnimations();
document.documentElement.setCurrentTime(0);
keypress(0x0D);
delayedSnapshot(2)">
<script xlink:href="event-util.js" type="text/javascript"/>
<circle id="circle" r="10"/>
<rect width="100" height="100" fill="red">
<set attributeName="fill" attributeType="CSS"
to="green" begin="accesskey(&#x0D;)" dur="4s"/>
</rect>
</svg>

After

Width:  |  Height:  |  Size: 544 B

View File

@ -1,21 +1,37 @@
// Allows a moment for events to be processed then performs a seek and runs
// a snapshot.
function delayedSnapshot(seekTimeInSeconds) {
function delayedSnapshot(seekTimeInSeconds)
{
// Allow time for events to be processed
window.setTimeout(finish, 10, seekTimeInSeconds);
}
function finish(seekTimeInSeconds) {
function finish(seekTimeInSeconds)
{
document.documentElement.pauseAnimations();
if (seekTimeInSeconds)
document.documentElement.setCurrentTime(seekTimeInSeconds);
document.documentElement.removeAttribute("class");
}
function click(targetId) {
function click(targetId)
{
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
var target = document.getElementById(targetId);
target.dispatchEvent(evt);
}
function keypress(charCode)
{
var evt = document.createEvent("KeyboardEvent");
evt.initKeyEvent("keypress", true, true, window,
false, // ctrlKeyArg
false, // altKeyArg
false, // shiftKeyArg
false, // metaKeyArg
0, // keyCode
charCode);
document.documentElement.dispatchEvent(evt);
}

View File

@ -27,3 +27,5 @@
== event-target-surgery-2.svg green-box-ref.svg
== event-target-surgery-3.svg green-box-ref.svg
== event-target-non-svg-1.xhtml green-box-ref.xhtml
== accesskey-entity-1.svg green-box-ref.svg
== accesskey-entity-2.svg green-box-ref.svg

View File

@ -3185,12 +3185,18 @@ pref("gfx.color_management.mode", 0);
// Initialize default render-mode.
pref("mozilla.widget.render-mode", -1);
// Initialize default accelerated layers
pref("mozilla.widget.accelerated-layers", true);
// Default value of acceleration for all widgets.
pref("layers.accelerate-all", false);
// Whether to allow acceleration on layers at all.
pref("layers.accelerate-none", false);
#ifdef XP_WIN
#ifndef WINCE
pref("mozilla.layers.prefer-opengl", false);
// Whether to disable the automatic detection and use of direct2d.
pref("gfx.direct2d.disabled", false);
pref("layers.prefer-opengl", false);
#endif
#endif

View File

@ -847,7 +847,7 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
if (PREF_CHANGED(UA_PREF("compatMode.firefox"))) {
rv = prefs->GetBoolPref(UA_PREF("compatMode.firefox"), &cVar);
if (NS_SUCCEEDED(rv) && cVar) {
mCompatFirefox.AssignLiteral("Firefox/" FIREFOX_VERSION);
mCompatFirefox.AssignLiteral("Firefox/" MOZ_UA_FIREFOX_VERSION);
} else {
mCompatFirefox.Truncate();
}

View File

@ -57,6 +57,8 @@
#include "nsIFormControl.h"
#include "nsIStyleSheetLinkingElement.h"
#include "nsIDOMDocumentType.h"
#include "nsIObserverService.h"
#include "mozilla/Services.h"
#include "nsIMutationObserver.h"
#include "nsIFormProcessor.h"
#include "nsIServiceManager.h"
@ -227,6 +229,23 @@ nsHtml5TreeOperation::Append(nsIContent* aNode,
return rv;
}
class nsDocElementCreatedNotificationRunner : public nsRunnable
{
public:
nsDocElementCreatedNotificationRunner(nsIDocument* aDoc)
: mDoc(aDoc)
{
}
NS_IMETHOD Run()
{
nsContentSink::NotifyDocElementCreated(mDoc);
return NS_OK;
}
nsCOMPtr<nsIDocument> mDoc;
};
nsresult
nsHtml5TreeOperation::AppendToDocument(nsIContent* aNode,
nsHtml5TreeOpExecutor* aBuilder)
@ -238,6 +257,12 @@ nsHtml5TreeOperation::AppendToDocument(nsIContent* aNode,
rv = doc->AppendChildTo(aNode, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
nsNodeUtils::ContentInserted(doc, aNode, childCount);
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
"Someone forgot to block scripts");
nsContentUtils::AddScriptRunner(
new nsDocElementCreatedNotificationRunner(doc));
return rv;
}

View File

@ -2773,7 +2773,7 @@ nsNavBookmarks::UpdateKeywordsHashForRemovedBookmark(PRInt64 aItemId)
NS_IMETHODIMP
nsNavBookmarks::SetKeywordForBookmark(PRInt64 aBookmarkId,
const nsAString& aKeyword)
const nsAString& aUserCasedKeyword)
{
NS_ENSURE_ARG_MIN(aBookmarkId, 1);
@ -2781,7 +2781,7 @@ nsNavBookmarks::SetKeywordForBookmark(PRInt64 aBookmarkId,
NS_ENSURE_SUCCESS(rv, rv);
// Shortcuts are always lowercased internally.
nsAutoString keyword(aKeyword);
nsAutoString keyword(aUserCasedKeyword);
ToLowerCase(keyword);
// Check if bookmark was already associated to a keyword.
@ -2899,21 +2899,22 @@ nsNavBookmarks::GetKeywordForBookmark(PRInt64 aBookmarkId, nsAString& aKeyword)
NS_IMETHODIMP
nsNavBookmarks::GetURIForKeyword(const nsAString& aKeyword, nsIURI** aURI)
nsNavBookmarks::GetURIForKeyword(const nsAString& aUserCasedKeyword,
nsIURI** aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_TRUE(!aKeyword.IsEmpty(), NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE(!aUserCasedKeyword.IsEmpty(), NS_ERROR_INVALID_ARG);
*aURI = nsnull;
// Shortcuts are always lowercased internally.
nsAutoString keyword(aKeyword);
nsAutoString keyword(aUserCasedKeyword);
ToLowerCase(keyword);
nsresult rv = EnsureKeywordsHash();
NS_ENSURE_SUCCESS(rv, rv);
keywordSearchData searchData;
searchData.keyword.Assign(aKeyword);
searchData.keyword.Assign(keyword);
searchData.itemId = -1;
mBookmarkToKeywordHash.EnumerateRead(SearchBookmarkForKeyword, &searchData);

View File

@ -65,6 +65,7 @@
#include "nsThreadUtils.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsMathUtils.h"
#include "mozIStorageCompletionCallback.h"
#include "nsNavBookmarks.h"
#include "nsAnnotationService.h"
@ -182,7 +183,8 @@ static const PRInt64 USECS_PER_DAY = LL_INIT(20, 500654080);
#endif
#define TOPIC_IDLE_DAILY "idle-daily"
#define TOPIC_PREF_CHANGED "nsPref:changed"
#define TOPIC_GLOBAL_SHUTDOWN "profile-before-change"
#define TOPIC_PROFILE_TEARDOWN "profile-change-teardown"
#define TOPIC_PROFILE_CHANGE "profile-before-change"
NS_IMPL_THREADSAFE_ADDREF(nsNavHistory)
NS_IMPL_THREADSAFE_RELEASE(nsNavHistory)
@ -312,8 +314,11 @@ protected:
class PlacesEvent : public nsRunnable
, public mozIStorageCompletionCallback
{
public:
NS_DECL_ISUPPORTS
PlacesEvent(const char* aTopic)
: mTopic(aTopic)
, mDoubleEnqueue(false)
@ -333,6 +338,12 @@ public:
return NS_OK;
}
NS_IMETHODIMP Complete()
{
Notify();
return NS_OK;
}
protected:
void Notify()
{
@ -351,6 +362,12 @@ protected:
bool mDoubleEnqueue;
};
NS_IMPL_ISUPPORTS2(
PlacesEvent
, mozIStorageCompletionCallback
, nsIRunnable
)
} // anonymouse namespace
@ -475,7 +492,8 @@ nsNavHistory::Init()
nsCOMPtr<nsIObserverService> obsSvc =
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
if (obsSvc) {
(void)obsSvc->AddObserver(this, TOPIC_GLOBAL_SHUTDOWN, PR_FALSE);
(void)obsSvc->AddObserver(this, TOPIC_PROFILE_TEARDOWN, PR_FALSE);
(void)obsSvc->AddObserver(this, TOPIC_PROFILE_CHANGE, PR_FALSE);
(void)obsSvc->AddObserver(this, TOPIC_IDLE_DAILY, PR_FALSE);
(void)obsSvc->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, PR_FALSE);
#ifdef MOZ_XUL
@ -5668,69 +5686,73 @@ nsNavHistory::Observe(nsISupports *aSubject, const char *aTopic,
{
NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
if (strcmp(aTopic, TOPIC_GLOBAL_SHUTDOWN) == 0) {
if (strcmp(aTopic, TOPIC_PROFILE_TEARDOWN) == 0) {
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (!os) {
NS_WARNING("Unable to shutdown Places: Observer Service unavailable.");
return NS_OK;
}
(void)os->RemoveObserver(this, TOPIC_GLOBAL_SHUTDOWN);
(void)os->RemoveObserver(this, TOPIC_PROFILE_TEARDOWN);
(void)os->RemoveObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC);
(void)os->RemoveObserver(this, TOPIC_IDLE_DAILY);
#ifdef MOZ_XUL
(void)os->RemoveObserver(this, TOPIC_AUTOCOMPLETE_FEEDBACK_INCOMING);
#endif
// Notify all Places users that we are about to shutdown. The notification
// is enqueued because there is network work on profile-before-change that
// should run before us.
nsRefPtr<PlacesEvent> shutdownEvent =
new PlacesEvent(TOPIC_PLACES_SHUTDOWN);
nsresult rv = NS_DispatchToMainThread(shutdownEvent);
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"Unable to shutdown Places: message dispatch failed.");
// If shutdown happens in the same scope as the service init, we should
// immediately notify the places-init topic. Otherwise, since it's an
// enqueued notification and the event loop won't spin, it could be notified
// after xpcom-shutdown, when the connection does not exist anymore.
nsCOMPtr<nsISimpleEnumerator> e;
nsresult rv = os->EnumerateObservers(TOPIC_PLACES_INIT_COMPLETE,
getter_AddRefs(e));
if (NS_SUCCEEDED(rv) && e) {
nsCOMPtr<nsIObserver> observer;
PRBool loop = PR_TRUE;
while(NS_SUCCEEDED(e->HasMoreElements(&loop)) && loop) {
e->GetNext(getter_AddRefs(observer));
(void)observer->Observe(observer, TOPIC_PLACES_INIT_COMPLETE, nsnull);
}
}
// Once everybody has been notified, proceed with the real shutdown.
// Note: PlacesEvent contains special code to double enqueue this
// notification because we must ensure any enqueued work from observers
// is complete before going on.
(void)os->AddObserver(this, TOPIC_PLACES_TEARDOWN, PR_FALSE);
nsRefPtr<PlacesEvent> teardownEvent =
new PlacesEvent(TOPIC_PLACES_TEARDOWN, true);
rv = NS_DispatchToMainThread(teardownEvent);
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"Unable to shutdown Places: message dispatch failed.");
// Notify all Places users that we are about to shutdown.
(void)os->NotifyObservers(nsnull, TOPIC_PLACES_SHUTDOWN, nsnull);
}
else if (strcmp(aTopic, TOPIC_PLACES_TEARDOWN) == 0) {
// Don't even try to notify observers from this point on, the category
// cache would init services that could not shutdown correctly or try to
// use our APIs.
mCanNotify = false;
else if (strcmp(aTopic, TOPIC_PROFILE_CHANGE) == 0) {
// Fire internal shutdown notifications.
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
(void)os->RemoveObserver(this, TOPIC_PROFILE_CHANGE);
// Double notification allows to correctly enqueue tasks without the need
// to enqueue notification events to the main-thread. There is no
// guarantee that the event loop will spin before xpcom-shutdown indeed,
// see bug 580892.
(void)os->NotifyObservers(nsnull, TOPIC_PLACES_WILL_CLOSE_CONNECTION, nsnull);
(void)os->NotifyObservers(nsnull, TOPIC_PLACES_CONNECTION_CLOSING, nsnull);
}
// Operations that are unlikely to create issues to implementers should go
// in global shutdown. Any other thing that must run really late must be
// in profile teardown. Any other thing that must run really late should be
// here instead.
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os)
(void)os->RemoveObserver(this, TOPIC_PLACES_TEARDOWN);
// Don't even try to notify observers from this point on, the category
// cache would init services that could try to use our APIs.
mCanNotify = false;
// Stop observing preferences changes.
if (mPrefBranch)
mPrefBranch->RemoveObserver("", this);
// Force a preferences save.
nsCOMPtr<nsIPrefService> prefService = do_QueryInterface(mPrefBranch);
if (prefService)
prefService->SavePrefFile(nsnull);
// Finalize all statements.
nsresult rv = FinalizeInternalStatements();
NS_ENSURE_SUCCESS(rv, rv);
// NOTE: We don't close the connection because the sync service could still
// need it for a final flush.
// Finally, close the connection.
nsRefPtr<PlacesEvent> closeListener =
new PlacesEvent(TOPIC_PLACES_CONNECTION_CLOSED);
(void)mDBConn->AsyncClose(closeListener);
}
#ifdef MOZ_XUL

View File

@ -93,12 +93,22 @@
// Fired after autocomplete feedback has been updated.
#define TOPIC_AUTOCOMPLETE_FEEDBACK_UPDATED "places-autocomplete-feedback-updated"
#endif
// Fired when Places is shutting down.
// Fired when Places is shutting down. Any code should stop accessing Places
// APIs after this notification. If you need to listen for Places shutdown
// you should only use this notification, next ones are intended only for
// internal Places use.
#define TOPIC_PLACES_SHUTDOWN "places-shutdown"
// Internal notification, called after places-shutdown.
// If you need to listen for Places shutdown, you should really use
// places-shutdown, because places-teardown is guaranteed to break your code.
#define TOPIC_PLACES_TEARDOWN "places-teardown"
// For Internal use only. Fired when connection is about to be closed, only
// cleanup tasks should run at this stage, nothing should be added to the
// database, nor APIs should be called.
#define TOPIC_PLACES_WILL_CLOSE_CONNECTION "places-will-close-connection"
// For Internal use only. Fired as the last notification before the connection
// is gone.
#define TOPIC_PLACES_CONNECTION_CLOSING "places-connection-closing"
// Fired when the connection has gone, nothing will work from now on.
#define TOPIC_PLACES_CONNECTION_CLOSED "places-connection-closed"
// Fired when Places found a locked database while initing.
#define TOPIC_DATABASE_LOCKED "places-database-locked"
// Fired after Places inited.

View File

@ -46,10 +46,8 @@ const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
// Use places-teardown to ensure we run last in the shutdown process.
// Any other implementer should use places-shutdown instead, since teardown is
// where things really break.
const kTopicShutdown = "places-teardown";
// A database flush should be the last operation during the shutdown process.
const kTopicShutdown = "places-connection-closing";
const kSyncFinished = "places-sync-finished";
const kDebugStopSync = "places-debug-stop-sync";
const kDebugStartSync = "places-debug-start-sync";
@ -125,22 +123,9 @@ nsPlacesDBFlush.prototype = {
this._timer = null;
}
// Other components could still make changes to history at this point,
// for example to clear private data on shutdown, so here we dispatch
// an event to the main thread so that we will sync after
// Places shutdown ensuring all data have been saved.
Services.tm.mainThread.dispatch({
_self: this,
run: function() {
// Flush any remaining change to disk tables.
this._self._flushWithQueries([kQuerySyncPlacesId, kQuerySyncHistoryVisitsId]);
// Close the database connection, this was the last sync and we can't
// ensure database coherence from now on.
this._self._finalizeInternalStatements();
this._self._db.asyncClose();
}
}, Ci.nsIThread.DISPATCH_NORMAL);
// Flush any remaining change to disk tables.
this._flushWithQueries([kQuerySyncPlacesId, kQuerySyncHistoryVisitsId]);
this._finalizeInternalStatements();
}
else if (aTopic == "nsPref:changed" && aData == kSyncPrefName) {
// Get the new pref value, and then update our timer

View File

@ -80,7 +80,8 @@ const nsPlacesExpirationFactory = {
////////////////////////////////////////////////////////////////////////////////
//// Constants
const TOPIC_SHUTDOWN = "places-shutdown";
// Last expiration step should run before the final sync.
const TOPIC_SHUTDOWN = "places-will-close-connection";
const TOPIC_PREF_CHANGED = "nsPref:changed";
const TOPIC_DEBUG_START_EXPIRATION = "places-debug-start-expiration";
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
@ -522,24 +523,16 @@ nsPlacesExpiration.prototype = {
this._timer = null;
}
// We must be sure to run after all other shutdown observers (but DBFlush)
// thus we enqueue the calls.
let self = this;
Services.tm.mainThread.dispatch({
run: function() {
// If we ran a clearHistory recently, or database id not dirty, we don't want to spend
// time expiring on shutdown. In such a case just expire session annotations.
let hasRecentClearHistory =
Date.now() - self._lastClearHistoryTime <
SHUTDOWN_WITH_RECENT_CLEARHISTORY_TIMEOUT_SECONDS * 1000;
let action = hasRecentClearHistory ||
self.status != STATUS.DIRTY ? ACTION.CLEAN_SHUTDOWN
: ACTION.SHUTDOWN;
self._expireWithActionAndLimit(action, LIMIT.LARGE);
self._finalizeInternalStatements();
}
}, Ci.nsIThread.DISPATCH_NORMAL);
// If we ran a clearHistory recently, or database id not dirty, we don't want to spend
// time expiring on shutdown. In such a case just expire session annotations.
let hasRecentClearHistory =
Date.now() - this._lastClearHistoryTime <
SHUTDOWN_WITH_RECENT_CLEARHISTORY_TIMEOUT_SECONDS * 1000;
let action = hasRecentClearHistory ||
this.status != STATUS.DIRTY ? ACTION.CLEAN_SHUTDOWN
: ACTION.SHUTDOWN;
this._expireWithActionAndLimit(action, LIMIT.LARGE);
this._finalizeInternalStatements();
}
else if (aTopic == TOPIC_PREF_CHANGED) {
this._loadPrefs();

View File

@ -40,6 +40,12 @@ let bs = PlacesUtils.bookmarks;
let db = DBConn();
function check_keyword(aItemId, aExpectedBookmarkKeyword, aExpectedURIKeyword) {
// All keywords are handled lowercased internally.
if (aExpectedURIKeyword)
aExpectedURIKeyword = aExpectedURIKeyword.toLowerCase();
if (aExpectedBookmarkKeyword)
aExpectedBookmarkKeyword = aExpectedBookmarkKeyword.toLowerCase();
if (aItemId) {
print("Check keyword for bookmark");
do_check_eq(bs.getKeywordForBookmark(aItemId), aExpectedBookmarkKeyword);
@ -50,8 +56,11 @@ function check_keyword(aItemId, aExpectedBookmarkKeyword, aExpectedURIKeyword) {
print("Check uri for keyword");
// This API can't tell which uri the user wants, so it returns a random one.
if (aExpectedURIKeyword)
if (aExpectedURIKeyword) {
do_check_true(/http:\/\/test[0-9]\.mozilla\.org/.test(bs.getURIForKeyword(aExpectedURIKeyword).spec));
// Check case insensitivity.
do_check_true(/http:\/\/test[0-9]\.mozilla\.org/.test(bs.getURIForKeyword(aExpectedURIKeyword.toUpperCase()).spec));
}
}
else {
stmt = db.createStatement(
@ -93,6 +102,8 @@ function run_test() {
check_keyword(itemId1, null, null);
bs.setKeywordForBookmark(itemId1, "keyword");
check_keyword(itemId1, "keyword", "keyword");
// Check case insensitivity.
check_keyword(itemId1, "kEyWoRd", "kEyWoRd");
print("Add another bookmark with the same uri, should not inherit keyword.");
let itemId1_bis = bs.insertBookmark(folderId,
@ -101,6 +112,8 @@ function run_test() {
"test1_bis");
check_keyword(itemId1_bis, null, "keyword");
// Check case insensitivity.
check_keyword(itemId1_bis, null, "kEyWoRd");
print("Set same keyword on another bookmark with a different uri.");
let itemId2 = bs.insertBookmark(folderId,
@ -108,7 +121,9 @@ function run_test() {
bs.DEFAULT_INDEX,
"test2");
check_keyword(itemId2, null, null);
bs.setKeywordForBookmark(itemId2, "keyword");
bs.setKeywordForBookmark(itemId2, "kEyWoRd");
check_keyword(itemId1, "kEyWoRd", "kEyWoRd");
// Check case insensitivity.
check_keyword(itemId1, "keyword", "keyword");
check_keyword(itemId1_bis, null, "keyword");
check_keyword(itemId2, "keyword", "keyword");

View File

@ -57,7 +57,7 @@ let (commonFile = do_get_file("../head_common.js", false)) {
function shutdownExpiration()
{
let expire = Cc["@mozilla.org/places/expiration;1"].getService(Ci.nsIObserver);
expire.observe(null, PlacesUtils.TOPIC_SHUTDOWN, null);
expire.observe(null, "places-will-close-connection", null);
}

View File

@ -40,9 +40,6 @@ const NS_APP_PROFILE_DIR_STARTUP = "ProfDS";
const NS_APP_HISTORY_50_FILE = "UHist";
const NS_APP_BOOKMARKS_50_FILE = "BMarks";
// Backwards compatible consts, use PlacesUtils properties if possible.
const TOPIC_GLOBAL_SHUTDOWN = "profile-before-change";
// Shortcuts to transactions type.
const TRANSITION_LINK = Ci.nsINavHistoryService.TRANSITION_LINK;
const TRANSITION_TYPED = Ci.nsINavHistoryService.TRANSITION_TYPED;
@ -347,11 +344,11 @@ function waitForClearHistory(aCallback) {
/**
* Simulates a Places shutdown.
*/
function shutdownPlaces()
function shutdownPlaces(aKeepAliveConnection)
{
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsIObserver);
hs.observe(null, TOPIC_GLOBAL_SHUTDOWN, null);
let hs = PlacesUtils.history.QueryInterface(Ci.nsIObserver);
hs.observe(null, "profile-change-teardown", null);
hs.observe(null, "profile-before-change", null);
}

View File

@ -50,7 +50,7 @@ const TEST_URI = "http://test.com/";
const kSyncPrefName = "syncDBTableIntervalInSecs";
const SYNC_INTERVAL = 600; // ten minutes
const kSyncFinished = "places-sync-finished";
const TOPIC_CONNECTION_CLOSED = "places-connection-closed";
var historyObserver = {
onVisit: function(aURI, aVisitId, aTime, aSessionId, aReferringId,
@ -64,9 +64,8 @@ hs.addObserver(historyObserver, false);
var observer = {
visitId: -1,
observe: function(aSubject, aTopic, aData) {
if (aTopic == kSyncFinished) {
// remove the observer, we don't need to observe sync on quit
os.removeObserver(this, kSyncFinished);
if (aTopic == TOPIC_CONNECTION_CLOSED) {
os.removeObserver(this, aTopic);
// visit id must be valid
do_check_neq(this.visitId, -1);
@ -75,7 +74,7 @@ var observer = {
}
}
}
os.addObserver(observer, kSyncFinished, false);
os.addObserver(observer, TOPIC_CONNECTION_CLOSED, false);
function run_test()
{

View File

@ -53,10 +53,7 @@ const TEST_URI = "http://test.com/";
const PREF_SYNC_INTERVAL = "syncDBTableIntervalInSecs";
const SYNC_INTERVAL = 600; // ten minutes
const TOPIC_SYNC_FINISHED = "places-sync-finished";
// Polling constants to check the connection closed status.
const POLLING_TIMEOUT_MS = 100;
const POLLING_MAX_PASSES = 20;
const TOPIC_CONNECTION_CLOSED = "places-connection-closed";
var historyObserver = {
visitId: -1,
@ -82,6 +79,7 @@ var observer = {
// The first sync is due to the insert bookmark.
// Simulate a clear private data just before shutdown.
bh.removeAllPages();
os.addObserver(shutdownObserver, TOPIC_CONNECTION_CLOSED, false);
// Immediately notify shutdown.
shutdownPlaces();
return;
@ -94,27 +92,16 @@ var observer = {
do_check_neq(historyObserver.visitId, -1);
// History must have been cleared.
do_check_true(historyObserver.cleared);
// The database connection will be closed after this sync, but we can't
// know how much time it will take, so we use a polling strategy.
do_timeout(POLLING_TIMEOUT_MS, check_results);
}
}
}
os.addObserver(observer, TOPIC_SYNC_FINISHED, false);
var gPasses = 0;
function check_results() {
if (++gPasses >= POLLING_MAX_PASSES) {
do_throw("Maximum time elapsdes waiting for Places database connection to close");
do_test_finished();
}
if (PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection.connectionReady) {
do_timeout(POLLING_TIMEOUT_MS, check_results);
return;
}
let shutdownObserver = {
observe: function(aSubject, aTopic, aData) {
os.removeObserver(this, aTopic);
do_check_false(PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection.connectionReady);
let dbConn = DBConn();
do_check_true(dbConn.connectionReady);
@ -144,6 +131,7 @@ function check_results() {
do_test_finished();
});
}
}
function run_test()

View File

@ -336,7 +336,10 @@ PopupNotifications.prototype = {
let doc = this.window.document;
let popupnotification = doc.createElementNS(XUL_NS, "popupnotification");
popupnotification.setAttribute("label", n.message);
popupnotification.setAttribute("id", n.id);
// Append "-notification" to the ID to try to avoid ID conflicts with other stuff
// in the document.
popupnotification.setAttribute("id", n.id + "-notification");
popupnotification.setAttribute("popupid", n.id);
if (n.mainAction) {
popupnotification.setAttribute("buttonlabel", n.mainAction.label);
popupnotification.setAttribute("buttonaccesskey", n.mainAction.accessKey);

View File

@ -469,7 +469,7 @@
<binding id="popup-notification">
<content align="start">
<xul:image class="popup-notification-icon"
xbl:inherits="popupid=id"/>
xbl:inherits="popupid"/>
<xul:vbox>
<xul:description class="popup-notification-description"
xbl:inherits="value=label"/>

View File

@ -10,8 +10,10 @@
<!ENTITY installFromFile.label "Install From File…">
<!ENTITY installFromFile.accesskey "I">
<!ENTITY cmd.back.tooltip "Go back one page">
<!ENTITY cmd.forward.tooltip "Go forward one page">
<!-- categories / views -->
<!-- LOCALIZATION NOTE: These should match the header-* entries in extensions.properties -->
<!ENTITY view.search.label "Search">
<!ENTITY view.discover.label "Get Add-ons">
<!ENTITY view.locales.label "Languages">
@ -21,6 +23,8 @@
<!ENTITY view.plugins.label "Plugins">
<!ENTITY view.recentUpdates.label "Recent Updates">
<!ENTITY view.availableUpdates.label "Available Updates">
<!ENTITY view.utilites.preferences.tooltip "Options for all add-ons">
<!ENTITY view.utilites.preferencesUnix.tooltip "Preferences for all add-ons">
<!-- addon updates -->
<!ENTITY updates.updateAddonsNow.label "Update Add-ons Now">
@ -41,8 +45,10 @@
<!ENTITY cmd.showDetails.accesskey "S">
<!ENTITY cmd.findUpdates.label "Find Updates">
<!ENTITY cmd.findUpdates.accesskey "F">
<!ENTITY cmd.preferences.label "Preferences">
<!ENTITY cmd.preferences.accesskey "P">
<!ENTITY cmd.preferencesWin.label "Options">
<!ENTITY cmd.preferencesWin.accesskey "O">
<!ENTITY cmd.preferencesUnix.label "Preferences">
<!ENTITY cmd.preferencesUnix.accesskey "P">
<!ENTITY cmd.about.label "About">
<!ENTITY cmd.about.accesskey "A">
@ -52,8 +58,10 @@
<!ENTITY cmd.disableAddon.accesskey "D">
<!ENTITY cmd.uninstallAddon.label "Remove">
<!ENTITY cmd.uninstallAddon.accesskey "R">
<!ENTITY cmd.showPreferences.label "Preferences">
<!ENTITY cmd.showPreferences.tooltip "Change this add-on's preferences">
<!ENTITY cmd.showPreferencesWin.label "Options">
<!ENTITY cmd.showPreferencesWin.tooltip "Change this add-on's options">
<!ENTITY cmd.showPreferencesUnix.label "Preferences">
<!ENTITY cmd.showPreferencesUnix.tooltip "Change this add-on's preferences">
<!ENTITY cmd.contribute.label "Contribute">
<!ENTITY cmd.contribute.accesskey "C">
<!ENTITY cmd.contribute.tooltip "Contribute to the development of this add-on">
@ -76,9 +84,12 @@
<!ENTITY detail.checkForUpdates.label "Check for updates">
<!ENTITY detail.checkForUpdates.accesskey "F">
<!ENTITY detail.checkForUpdates.tooltip "Check for updates for this add-on">
<!ENTITY detail.showPreferences.label "Preferences">
<!ENTITY detail.showPreferences.accesskey "P">
<!ENTITY detail.showPreferences.tooltip "Change this add-on's preferences">
<!ENTITY detail.showPreferencesWin.label "Options">
<!ENTITY detail.showPreferencesWin.accesskey "O">
<!ENTITY detail.showPreferencesWin.tooltip "Change this add-on's Options">
<!ENTITY detail.showPreferencesUnix.label "Preferences">
<!ENTITY detail.showPreferencesUnix.accesskey "P">
<!ENTITY detail.showPreferencesUnix.tooltip "Change this add-on's preferences">
<!-- ratings -->

View File

@ -6,20 +6,6 @@ aboutWindowVersionString=version %S
#LOCALIZATION NOTE (aboutAddon) %S is the addon name
aboutAddon=About %S
#LOCALIZATION NOTE These should match the view.*.label entities in extensions.dtd
header-search=Search Results
header-discover=Get Add-ons
header-locale=Languages
header-searchengine=Search Engines
header-extension=Extensions
header-theme=Themes
header-plugin=Plugins
header-recentUpdates=Recent Updates
header-availableUpdates=Available Updates
#LOCALIZATION NOTE (header-goBack) %S is the name of the pane to go back to
header-goBack=Back to %S
#LOCALIZATION NOTE (uninstallNotice) %S is the add-on name
uninstallNotice=%S has been removed.

View File

@ -52,16 +52,22 @@
<!ENTITY details.link "Details">
<!ENTITY error.title "Update Failed">
<!ENTITY error.label "There were problems checking for, downloading, or installing this
update. &brandShortName; could not be updated because:">
<!ENTITY errorManual.label "You can update &brandShortName; manually by visiting this link
and downloading the latest version:">
<!ENTITY errorpatching.title "Update Failed">
<!ENTITY errorpatching.intro "The partial Update could not be applied.
&brandShortName; will try again by downloading a complete Update.">
<!ENTITY errorCertAttrNoUpdate.label "Something is preventing &brandShortName; from updating securely.
Please check you have the latest version of &brandShortName; at:">
<!ENTITY errorCertAttrHasUpdate.label "Something is trying to trick &brandShortName; into accepting an
insecure update. Please contact your network provider and seek help.">
<!ENTITY finishedPage.title "Update Ready to Install">
<!ENTITY finishedPage.text "The update will be installed the next time &brandShortName; starts. You
can restart &brandShortName; now, or continue working and restart later.">

View File

@ -32,7 +32,6 @@ updateType_minor=Security Update
# LOCALIZATION NOTE: When present %S is brandShortName
verificationError=%S could not confirm the integrity of the update package.
errorsPageHeader=Update Failed
licenseContentNotFound=The license file for this version could not be found. Please visit the %S homepage for more information.
updateMoreInfoContentNotFound=Additional details about this version could not be found. Please visit the %S homepage for more information.
resumePausedAfterCloseTitle=Software Update

View File

@ -93,9 +93,11 @@ XPCOMUtils.defineLazyGetter(gStrings, "appVersion", function() {
return Services.appinfo.version;
});
window.addEventListener("load", initialize, false);
window.addEventListener("unload", shutdown, false);
window.addEventListener("popstate", function(event) {
gViewController.statePopped(event);
}, false);
var gPendingInitializations = 1;
__defineGetter__("gIsInitializing", function() gPendingInitializations > 0);
@ -105,19 +107,6 @@ function initialize() {
gHeader.initialize();
gViewController.initialize();
gEventManager.initialize();
var view = VIEW_DEFAULT;
if (gCategories.node.selectedItem &&
gCategories.node.selectedItem.id != "category-search")
view = gCategories.node.selectedItem.value;
if ("arguments" in window && window.arguments.length > 0) {
if ("view" in window.arguments[0])
view = window.arguments[0].view;
}
gViewController.loadView(view);
notifyInitialized();
}
function notifyInitialized() {
@ -140,8 +129,14 @@ function shutdown() {
}
// Used by external callers to load a specific view into the manager
function loadView(aViewId, aCallback) {
gViewController.loadView(aViewId, aCallback);
function loadView(aViewId) {
if (!gViewController.initialViewSelected) {
// The caller opened the window and immediately loaded the view so it
// should be the initial history entry
gViewController.loadInitialView(aViewId);
} else {
gViewController.loadView(aViewId);
}
}
var gEventManager = {
@ -258,9 +253,9 @@ var gViewController = {
currentViewId: "",
currentViewObj: null,
currentViewRequest: 0,
previousViewId: "",
viewObjects: {},
viewChangeCallback: null,
initialViewSelected: false,
initialize: function() {
this.viewPort = document.getElementById("view-port");
@ -294,6 +289,32 @@ var gViewController = {
}
},
statePopped: function(e) {
// If this is a navigation to a previous state then load that state
if (e.state) {
this.loadViewInternal(e.state.view, e.state.previousView);
return;
}
// If the initial view has already been selected (by a call to loadView) then
// bail out now
if (this.initialViewSelected)
return;
// Otherwise load the default view
var view = VIEW_DEFAULT;
if (gCategories.node.selectedItem &&
gCategories.node.selectedItem.id != "category-search")
view = gCategories.node.selectedItem.value;
if ("arguments" in window && window.arguments.length > 0) {
if ("view" in window.arguments[0])
view = window.arguments[0].view;
}
this.loadInitialView(view);
},
parseViewId: function(aViewId) {
var matchRegex = /^addons:\/\/([^\/]+)\/(.*)$/;
var [,viewType, viewParam] = aViewId.match(matchRegex) || [];
@ -301,13 +322,32 @@ var gViewController = {
},
get isLoading() {
return this.currentViewObj.node.hasAttribute("loading");
return !this.currentViewObj || this.currentViewObj.node.hasAttribute("loading");
},
loadView: function(aViewId, aCallback) {
loadView: function(aViewId) {
if (aViewId == this.currentViewId)
return;
window.history.pushState({
view: aViewId,
previousView: this.currentViewId
}, document.title);
this.loadViewInternal(aViewId, this.currentViewId);
},
loadInitialView: function(aViewId) {
window.history.replaceState({
view: aViewId,
previousView: null
}, document.title);
this.loadViewInternal(aViewId, null);
this.initialViewSelected = true;
notifyInitialized();
},
loadViewInternal: function(aViewId, aPreviousView) {
var view = this.parseViewId(aViewId);
if (!view.type || !(view.type in this.viewObjects))
@ -329,25 +369,41 @@ var gViewController = {
}
}
gCategories.select(aViewId);
this.previousViewId = this.currentViewId;
gCategories.select(aViewId, aPreviousView);
this.currentViewId = aViewId;
this.currentViewObj = viewObj;
this.viewChangeCallback = aCallback;
this.viewPort.selectedPanel = this.currentViewObj.node;
this.viewPort.selectedPanel.setAttribute("loading", "true");
this.currentViewObj.show(view.param, ++this.currentViewRequest);
},
// Moves back in the document history and removes the current history entry
popState: function(aCallback) {
this.viewChangeCallback = function() {
// TODO To ensure we can't go forward again we put an additional entry for
// the current page into the history. Ideally we would just strip the
// history but there doesn't seem to be a way to do that. Bug 590661
window.history.pushState({
view: gViewController.currentViewId,
previousView: gViewController.currentViewId
}, document.title);
this.updateCommands();
if (aCallback)
aCallback();
};
window.history.back();
},
notifyViewChanged: function() {
this.viewPort.selectedPanel.removeAttribute("loading");
if (this.viewChangeCallback)
if (this.viewChangeCallback) {
this.viewChangeCallback();
this.viewChangeCallback = null;
}
var event = document.createEvent("Events");
event.initEvent("ViewChanged", true, true);
@ -355,6 +411,28 @@ var gViewController = {
},
commands: {
cmd_back: {
isEnabled: function() {
return window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.canGoBack;
},
doCommand: function() {
window.history.back();
}
},
cmd_forward: {
isEnabled: function() {
return window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.canGoForward;
},
doCommand: function() {
window.history.forward();
}
},
cmd_restartApp: {
isEnabled: function() true,
doCommand: function() {
@ -616,7 +694,7 @@ var gViewController = {
return;
}
gViewController.loadView(gViewController.previousViewId, function() {
gViewController.popState(function() {
gViewController.currentViewObj.getListItemForID(aAddon.id).uninstall();
});
},
@ -921,15 +999,17 @@ var gCategories = {
});
},
select: function(aId) {
select: function(aId, aPreviousView) {
var view = gViewController.parseViewId(aId);
if (view.type == "detail") {
aId = aPreviousView;
view = gViewController.parseViewId(aPreviousView);
}
if (this.node.selectedItem &&
this.node.selectedItem.value == aId)
return;
var view = gViewController.parseViewId(aId);
if (view.type == "detail")
return;
if (view.type == "search")
var item = this._search;
else
@ -942,6 +1022,8 @@ var gCategories = {
this.node.selectedItem = item;
this.node.suppressOnSelect = false;
this.node.ensureElementIsVisible(item);
// When supressing onselect last-selected doesn't get updated
this.node.setAttribute("last-selected", item.id);
this.maybeHideSearch();
}
@ -970,21 +1052,12 @@ var gCategories = {
var gHeader = {
_search: null,
_searching: null,
_name: null,
_link: null,
_dest: "",
initialize: function() {
this._name = document.getElementById("header-name");
this._link = document.getElementById("header-link");
this._search = document.getElementById("header-search");
this._searching = document.getElementById("header-searching");
var self = this;
this._link.addEventListener("command", function() {
gViewController.loadView(gViewController.previousViewId);
}, false);
this._search.addEventListener("command", function(aEvent) {
var query = aEvent.target.value;
if (query.length == 0)
@ -992,21 +1065,6 @@ var gHeader = {
gViewController.loadView("addons://search/" + encodeURIComponent(query));
}, false);
this.setName("");
},
setName: function(aName) {
this._name.value = aName;
this._name.hidden = false;
this._link.hidden = true;
},
showBackButton: function() {
this._link.label = gStrings.ext.formatStringFromName("header-goBack",
[this._name.value], 1);
this._name.hidden = true;
this._link.hidden = false;
},
get searchQuery() {
@ -1069,7 +1127,6 @@ var gDiscoverView = {
},
show: function() {
gHeader.setName(gStrings.ext.GetStringFromName("header-discover"));
// load content only if we're not already showing something on AMO
// XXXunf should only be comparing hostname. bug 557698
if (this._browser.currentURI.spec.indexOf(this._browser.homePage) == -1)
@ -1127,7 +1184,6 @@ var gSearchView = {
},
show: function(aQuery, aRequest) {
gHeader.setName(gStrings.ext.GetStringFromName("header-search"));
gHeader.isSearching = true;
this.showEmptyNotice(false);
@ -1360,7 +1416,6 @@ var gListView = {
},
show: function(aType, aRequest) {
gHeader.setName(gStrings.ext.GetStringFromName("header-" + aType));
this.showEmptyNotice(false);
while (this._listBox.itemCount > 0)
@ -1499,7 +1554,6 @@ var gDetailView = {
this._loadingTimer = setTimeout(function() {
self.node.setAttribute("loading-extended", true);
}, LOADING_MSG_DELAY);
gHeader.showBackButton();
var view = gViewController.currentViewId;
@ -1624,7 +1678,7 @@ var gDetailView = {
},
onUninstalled: function() {
gViewController.loadView(gViewController.previousViewId);
gViewController.popState();
},
onOperationCancelled: function() {
@ -1678,8 +1732,6 @@ var gUpdatesView = {
},
show: function(aType, aRequest) {
gHeader.setName(gStrings.ext.GetStringFromName("header-" + aType + "Updates"));
document.getElementById("empty-availableUpdates-msg").hidden = aType != "available";
document.getElementById("empty-recentUpdates-msg").hidden = aType != "recent";
this.showEmptyNotice(false);

View File

@ -21,6 +21,7 @@
-
- Contributor(s):
- Blair McBride <bmcbride@mozilla.com>
- David Dahl <ddahl@mozilla.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
@ -801,8 +802,13 @@
</xul:hbox>
<xul:hbox anonid="control-container" class="control-container">
<xul:button anonid="preferences-btn" class="addon-control"
label="&cmd.showPreferences.label;"
tooltiptext="&cmd.showPreferences.tooltip;"
#ifdef XP_WIN
label="&cmd.showPreferencesWin.label;"
tooltiptext="&cmd.showPreferencesWin.tooltip;"
#else
label="&cmd.showPreferencesUnix.label;"
tooltiptext="&cmd.showPreferencesUnix.tooltip;"
#endif
oncommand="document.getBindingParent(this).showPreferences();"/>
<xul:button anonid="enable-btn" class="addon-control enable"
label="&cmd.enableAddon.label;"

View File

@ -21,6 +21,7 @@
-
- Contributor(s):
- Blair McBride <bmcbride@mozilla.com>
- David Dahl <ddahl@mozilla.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
@ -69,8 +70,13 @@
accesskey="&cmd.findUpdates.accesskey;"/>
<menuseparator/>
<menuitem id="menuitem_preferences" command="cmd_showItemPreferences"
label="&cmd.preferences.label;"
accesskey="&cmd.preferences.accesskey;"/>
#ifdef XP_WIN
label="&cmd.preferencesWin.label;"
accesskey="&cmd.preferencesWin.accesskey;"/>
#else
label="&cmd.preferencesUnix.label;"
accesskey="&cmd.preferencesUnix.accesskey;"/>
#endif
<menuitem id="menuitem_about" command="cmd_showItemAbout"
label="&cmd.about.label;"
accesskey="&cmd.about.accesskey;"/>
@ -88,6 +94,8 @@
<command id="cmd_goToAvailableUpdates"/>
<command id="cmd_toggleBackgroundUpdateCheck"/>
<command id="cmd_installFromFile"/>
<command id="cmd_back"/>
<command id="cmd_forward"/>
</commandset>
<!-- view commands - these act on the selected addon -->
@ -107,8 +115,10 @@
<!-- main header -->
<hbox id="header" align="center">
<label id="header-name"/>
<button id="header-link"/>
<button id="back-btn" class="nav-button" command="cmd_back"
tooltiptext="&cmd.back.tooltip;"/>
<button id="forward-btn" class="nav-button" command="cmd_forward"
tooltiptext="&cmd.forward.tooltip;"/>
<spacer flex="1"/>
<hbox id="updates-container" align="center">
<image class="spinner"/>
@ -127,7 +137,12 @@
label="&updates.restart.label;"
command="cmd_restartApp"/>
</hbox>
<button id="header-utils-btn" type="menu">
<button id="header-utils-btn" type="menu"
#ifdef XP_WIN
tooltiptext="&view.utilites.preferences.tooltip;">
#else
tooltiptext="&view.utilites.preferencesUnix.tooltip;">
#endif
<menupopup id="utils-menu">
<menuitem id="utils-updateNow"
label="&updates.updateAddonsNow.label;"
@ -346,9 +361,15 @@
tooltiptext="&detail.checkForUpdates.tooltip;"
command="cmd_findItemUpdates"/>
<button id="detail-prefs" class="addon-control"
label="&detail.showPreferences.label;"
accesskey="&detail.showPreferences.accesskey;"
tooltiptext="&detail.showPreferences.tooltip;"
#ifdef XP_WIN
label="&detail.showPreferencesWin.label;"
accesskey="&detail.showPreferencesWin.accesskey;"
tooltiptext="&detail.showPreferencesWin.tooltip;"
#else
label="&detail.showPreferencesUnix.label;"
accesskey="&detail.showPreferencesUnix.accesskey;"
tooltiptext="&detail.showPreferencesUnix.tooltip;"
#endif
command="cmd_showItemPreferences"/>
</vbox>
<grid class="detail-meta fade" flex="1">

View File

@ -1,9 +1,9 @@
toolkit.jar:
% content mozapps %content/mozapps/
content/mozapps/extensions/extensions.xul (content/extensions.xul)
* content/mozapps/extensions/extensions.xul (content/extensions.xul)
content/mozapps/extensions/extensions.css (content/extensions.css)
content/mozapps/extensions/extensions.js (content/extensions.js)
content/mozapps/extensions/extensions.xml (content/extensions.xml)
* content/mozapps/extensions/extensions.xml (content/extensions.xml)
content/mozapps/extensions/updateinfo.xsl (content/updateinfo.xsl)
content/mozapps/extensions/extensions-content.js (content/extensions-content.js)
* content/mozapps/extensions/about.xul (content/about.xul)

View File

@ -52,6 +52,7 @@ _TEST_FILES = \
browser_bug557956.rdf \
browser_bug557956_8_2.xpi \
browser_bug557956_9_2.xpi \
browser_bug562797.js \
browser_bug562890.js \
browser_bug562899.js \
browser_bug562992.js \

View File

@ -0,0 +1,502 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* Tests that history navigation works for the add-ons manager. Only used if
* in-content UI is supported for this application.
*/
function test() {
// XXX
ok(true, "Test temporarily disabled due to timeouts\n");
return;
if (!gUseInContentUI)
return;
waitForExplicitFinish();
var gProvider = new MockProvider();
gProvider.createAddons([{
id: "test1@tests.mozilla.org",
name: "Test add-on 1",
description: "foo"
},
{
id: "test2@tests.mozilla.org",
name: "Test add-on 2",
description: "bar"
},
{
id: "test3@tests.mozilla.org",
name: "Test add-on 3",
type: "theme",
description: "bar"
}]);
run_next_test();
}
function end_test() {
finish();
}
function is_in_list(aManager, view, canGoBack, canGoForward) {
var doc = aManager.document;
is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category");
is(doc.getElementById("view-port").selectedPanel.id, "list-view", "Should be on the right view");
is(gBrowser.canGoBack, canGoBack, "canGoBack should be correct");
is(!doc.getElementById("back-btn").disabled, canGoBack, "Back button should have the right state");
is(gBrowser.canGoForward, canGoForward, "canGoForward should be correct");
is(!doc.getElementById("forward-btn").disabled, canGoForward, "Forward button should have the right state");
}
function is_in_search(aManager, query, canGoBack, canGoForward) {
var doc = aManager.document;
is(doc.getElementById("categories").selectedItem.value, "addons://search/", "Should be on the right category");
is(doc.getElementById("view-port").selectedPanel.id, "search-view", "Should be on the right view");
is(doc.getElementById("header-search").value, query, "Should have used the right query");
is(gBrowser.canGoBack, canGoBack, "canGoBack should be correct");
is(!doc.getElementById("back-btn").disabled, canGoBack, "Back button should have the right state");
is(gBrowser.canGoForward, canGoForward, "canGoForward should be correct");
is(!doc.getElementById("forward-btn").disabled, canGoForward, "Forward button should have the right state");
}
function is_in_detail(aManager, view, canGoBack, canGoForward) {
var doc = aManager.document;
is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category");
is(doc.getElementById("view-port").selectedPanel.id, "detail-view", "Should be on the right view");
is(gBrowser.canGoBack, canGoBack, "canGoBack should be correct");
is(!doc.getElementById("back-btn").disabled, canGoBack, "Back button should have the right state");
is(gBrowser.canGoForward, canGoForward, "canGoForward should be correct");
is(!doc.getElementById("forward-btn").disabled, canGoForward, "Forward button should have the right state");
}
// Tests simple forward and back navigation and that the right heading and
// category is selected
add_test(function() {
open_manager("addons://list/extension", function(aManager) {
info("Part 1");
is_in_list(aManager, "addons://list/extension", false, false);
EventUtils.synthesizeMouse(aManager.document.getElementById("category-plugins"), 2, 2, { }, aManager);
wait_for_view_load(aManager, function(aManager) {
info("Part 2");
is_in_list(aManager, "addons://list/plugin", true, false);
gBrowser.goBack();
wait_for_view_load(aManager, function(aManager) {
info("Part 3");
is_in_list(aManager, "addons://list/extension", false, true);
gBrowser.goForward();
wait_for_view_load(aManager, function(aManager) {
info("Part 4");
is_in_list(aManager, "addons://list/plugin", true, false);
gBrowser.goBack();
wait_for_view_load(aManager, function(aManager) {
info("Part 5");
is_in_list(aManager, "addons://list/extension", false, true);
EventUtils.synthesizeMouse(get_addon_element(aManager, "test1@tests.mozilla.org"),
2, 2, { clickCount: 2 }, aManager);
wait_for_view_load(aManager, function(aManager) {
info("Part 6");
is_in_detail(aManager, "addons://list/extension", true, false);
gBrowser.goBack();
wait_for_view_load(aManager, function(aManager) {
info("Part 7");
is_in_list(aManager, "addons://list/extension", false, true);
close_manager(aManager, run_next_test);
});
});
});
});
});
});
});
});
// Tests that browsing to the add-ons manager from a website and going back works
add_test(function() {
info("Part 1");
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.loadURI("http://example.com/");
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "http://example.com/")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, false);
//Must let the load complete for it to go into the session history
executeSoon(function() {
info("Part 2");
ok(!gBrowser.canGoBack, "Should not be able to go back");
ok(!gBrowser.canGoForward, "Should not be able to go forward");
gBrowser.loadURI("about:addons");
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "about:addons")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, true);
wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) {
info("Part 3");
is_in_list(aManager, "addons://list/extension", true, false);
gBrowser.goBack();
gBrowser.addEventListener("pageshow", function() {
gBrowser.removeEventListener("pageshow", arguments.callee, false);
info("Part 4");
is(gBrowser.currentURI.spec, "http://example.com/", "Should be showing the webpage");
ok(!gBrowser.canGoBack, "Should not be able to go back");
ok(gBrowser.canGoForward, "Should be able to go forward");
gBrowser.goForward();
gBrowser.addEventListener("pageshow", function() {
gBrowser.removeEventListener("pageshow", arguments.callee, false);
wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) {
info("Part 5");
is_in_list(aManager, "addons://list/extension", true, false);
close_manager(aManager, run_next_test);
});
}, false);
}, false);
});
}, true);
});
}, false);
});
// Tests that opening a custom first view only stores a single history entry
add_test(function() {
open_manager("addons://list/plugin", function(aManager) {
info("Part 1");
is_in_list(aManager, "addons://list/plugin", false, false);
EventUtils.synthesizeMouse(aManager.document.getElementById("category-extensions"), 2, 2, { }, aManager);
wait_for_view_load(aManager, function(aManager) {
info("Part 2");
is_in_list(aManager, "addons://list/extension", true, false);
gBrowser.goBack();
wait_for_view_load(aManager, function(aManager) {
info("Part 3");
is_in_list(aManager, "addons://list/plugin", false, true);
close_manager(aManager, run_next_test);
});
});
});
});
// Tests that opening a view while the manager is already open adds a new
// history entry
add_test(function() {
open_manager("addons://list/extension", function(aManager) {
info("Part 1");
is_in_list(aManager, "addons://list/extension", false, false);
aManager.loadView("addons://list/plugin");
wait_for_view_load(aManager, function(aManager) {
info("Part 2");
is_in_list(aManager, "addons://list/plugin", true, false);
gBrowser.goBack();
wait_for_view_load(aManager, function(aManager) {
info("Part 3");
is_in_list(aManager, "addons://list/extension", false, true);
gBrowser.goForward();
wait_for_view_load(aManager, function(aManager) {
info("Part 4");
is_in_list(aManager, "addons://list/plugin", true, false);
close_manager(aManager, run_next_test);
});
});
});
});
});
// Tests than navigating to a website and then going back returns to the
// previous view
add_test(function() {
open_manager("addons://list/plugin", function(aManager) {
info("Part 1");
is_in_list(aManager, "addons://list/plugin", false, false);
gBrowser.loadURI("http://example.com/");
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "http://example.com/")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, false);
info("Part 2");
executeSoon(function() {
ok(gBrowser.canGoBack, "Should be able to go back");
ok(!gBrowser.canGoForward, "Should not be able to go forward");
gBrowser.goBack();
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "about:addons")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, false);
wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) {
info("Part 3");
is_in_list(aManager, "addons://list/plugin", false, true);
gBrowser.goForward();
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "http://example.com/")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, false);
info("Part 4");
executeSoon(function() {
ok(gBrowser.canGoBack, "Should be able to go back");
ok(!gBrowser.canGoForward, "Should not be able to go forward");
gBrowser.goBack();
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "about:addons")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, false);
wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) {
info("Part 5");
is_in_list(aManager, "addons://list/plugin", false, true);
close_manager(aManager, run_next_test);
});
}, false);
});
}, false);
});
}, false);
});
}, false);
});
});
// Tests that going back to search results works
add_test(function() {
open_manager("addons://list/extension", function(aManager) {
info("Part 1");
is_in_list(aManager, "addons://list/extension", false, false);
var search = aManager.document.getElementById("header-search");
search.focus();
search.value = "bar";
EventUtils.synthesizeKey("VK_RETURN", {});
wait_for_view_load(aManager, function(aManager) {
info("Part 2");
is_in_search(aManager, "bar", true, false);
check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]);
EventUtils.synthesizeMouse(get_addon_element(aManager, "test2@tests.mozilla.org"),
2, 2, { clickCount: 2 }, aManager);
wait_for_view_load(aManager, function(aManager) {
info("Part 3");
is_in_detail(aManager, "addons://search/", true, false);
gBrowser.goBack();
wait_for_view_load(aManager, function(aManager) {
info("Part 4");
is_in_search(aManager, "bar", true, true);
check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]);
gBrowser.goForward();
wait_for_view_load(aManager, function(aManager) {
info("Part 5");
is_in_detail(aManager, "addons://search/", true, false);
close_manager(aManager, run_next_test);
});
});
});
});
});
});
// Tests that going back to a detail view loaded from a search result works
add_test(function() {
open_manager(null, function(aManager) {
info("Part 1");
is_in_list(aManager, "addons://list/extension", false, false);
var search = aManager.document.getElementById("header-search");
search.focus();
search.value = "bar";
EventUtils.synthesizeKey("VK_RETURN", {});
wait_for_view_load(aManager, function(aManager) {
info("Part 2");
is_in_search(aManager, "bar", true, false);
check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]);
EventUtils.synthesizeMouse(get_addon_element(aManager, "test2@tests.mozilla.org"),
2, 2, { clickCount: 2 }, aManager);
wait_for_view_load(aManager, function(aManager) {
info("Part 3");
is_in_detail(aManager, "addons://search/", true, false);
gBrowser.loadURI("http://example.com/");
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "http://example.com/")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, false);
info("Part 4");
executeSoon(function() {
ok(gBrowser.canGoBack, "Should be able to go back");
ok(!gBrowser.canGoForward, "Should not be able to go forward");
gBrowser.goBack();
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "about:addons")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, false);
wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) {
info("Part 5");
is_in_detail(aManager, "addons://search/", true, true);
gBrowser.goBack();
wait_for_view_load(aManager, function(aManager) {
info("Part 6");
is_in_search(aManager, "bar", true, true);
check_all_in_list(aManager, ["test2@tests.mozilla.org", "test3@tests.mozilla.org"]);
close_manager(aManager, run_next_test);
});
});
}, false);
});
}, false);
});
});
});
});
// Tests that refreshing a list view does not affect the history
add_test(function() {
open_manager(null, function(aManager) {
info("Part 1");
is_in_list(aManager, "addons://list/extension", false, false);
EventUtils.synthesizeMouse(aManager.document.getElementById("category-plugins"), 2, 2, { }, aManager);
wait_for_view_load(aManager, function(aManager) {
info("Part 2");
is_in_list(aManager, "addons://list/plugin", true, false);
gBrowser.reload();
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "about:addons")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, false);
wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) {
info("Part 3");
is_in_list(aManager, "addons://list/plugin", true, false);
gBrowser.goBack();
wait_for_view_load(aManager, function(aManager) {
info("Part 4");
is_in_list(aManager, "addons://list/extension", false, true);
close_manager(aManager, run_next_test);
});
});
}, false);
});
});
});
// Tests that refreshing a detail view does not affect the history
add_test(function() {
open_manager(null, function(aManager) {
info("Part 1");
is_in_list(aManager, "addons://list/extension", false, false);
EventUtils.synthesizeMouse(get_addon_element(aManager, "test1@tests.mozilla.org"),
2, 2, { clickCount: 2 }, aManager);
wait_for_view_load(aManager, function(aManager) {
info("Part 2");
is_in_detail(aManager, "addons://list/extension", true, false);
gBrowser.reload();
gBrowser.addEventListener("pageshow", function(event) {
if (event.target.location != "about:addons")
return;
gBrowser.removeEventListener("pageshow", arguments.callee, false);
wait_for_view_load(gBrowser.contentWindow.wrappedJSObject, function(aManager) {
info("Part 3");
is_in_detail(aManager, "addons://list/extension", true, false);
gBrowser.goBack();
wait_for_view_load(aManager, function(aManager) {
info("Part 4");
is_in_list(aManager, "addons://list/extension", false, true);
close_manager(aManager, run_next_test);
});
});
}, false);
});
});
});
// Tests that removing an extension from the detail view goes back and doesn't
// allow you to go forward again.
add_test(function() {
open_manager(null, function(aManager) {
info("Part 1");
is_in_list(aManager, "addons://list/extension", false, false);
EventUtils.synthesizeMouse(get_addon_element(aManager, "test1@tests.mozilla.org"),
2, 2, { clickCount: 2 }, aManager);
wait_for_view_load(aManager, function(aManager) {
info("Part 2");
is_in_detail(aManager, "addons://list/extension", true, false);
EventUtils.synthesizeMouse(aManager.document.getElementById("detail-uninstall"),
2, 2, { }, aManager);
wait_for_view_load(aManager, function() {
// TODO until bug 590661 is fixed the back button will be enabled
is_in_list(aManager, "addons://list/extension", true, false);
close_manager(aManager, run_next_test);
});
});
});
});

View File

@ -437,10 +437,8 @@ add_test(function() {
var version = gManagerWindow.document.getElementById("detail-version").value;
is(version, item.mAddon.version, "Version in detail view should be correct");
var headerLink = gManagerWindow.document.getElementById("header-link");
is(headerLink.hidden, false, "Header link should be showing in detail view");
EventUtils.synthesizeMouse(headerLink, 2, 2, { }, gManagerWindow);
EventUtils.synthesizeMouse(gManagerWindow.document.getElementById("back-btn"),
2, 2, { }, gManagerWindow);
wait_for_view_load(gManagerWindow, run_next_double_click_test);
});
}

View File

@ -20,6 +20,8 @@ const PREF_SEARCH_MAXRESULTS = "extensions.getAddons.maxResults";
var gPendingTests = [];
var gTestsRun = 0;
var gUseInContentUI = ("switchToTabHavingURI" in window);
// Turn logging on for all tests
Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true);
// Turn off remote results in searches
@ -71,6 +73,49 @@ function get_addon_file_url(aFilename) {
}
}
function check_all_in_list(aManager, aIds, aIgnoreExtras) {
var doc = aManager.document;
var view = doc.getElementById("view-port").selectedPanel;
var listid = view.id == "search-view" ? "search-list" : "addon-list";
var list = doc.getElementById(listid);
var inlist = [];
var node = list.firstChild;
while (node) {
if (node.value)
inlist.push(node.value);
node = node.nextSibling;
}
for (var i = 0; i < aIds.length; i++) {
if (inlist.indexOf(aIds[i]) == -1)
ok(false, "Should find " + aIds[i] + " in the list");
}
if (aIgnoreExtras)
return;
for (i = 0; i < inlist.length; i++) {
if (aIds.indexOf(inlist[i]) == -1)
ok(false, "Shouldn't have seen " + inlist[i] + " in the list");
}
}
function get_addon_element(aManager, aId) {
var doc = aManager.document;
var view = doc.getElementById("view-port").selectedPanel;
var listid = view.id == "search-view" ? "search-list" : "addon-list";
var list = doc.getElementById(listid);
var node = list.firstChild;
while (node) {
if (node.value == aId)
return node;
node = node.nextSibling;
}
return null;
}
function wait_for_view_load(aManagerWindow, aCallback, aForceWait) {
if (!aForceWait && !aManagerWindow.gViewController.isLoading) {
aCallback(aManagerWindow);
@ -89,6 +134,7 @@ function wait_for_manager_load(aManagerWindow, aCallback) {
return;
}
info("Waiting for initialization");
aManagerWindow.document.addEventListener("Initialized", function() {
aManagerWindow.document.removeEventListener("Initialized", arguments.callee, false);
aCallback(aManagerWindow);
@ -111,7 +157,7 @@ function open_manager(aView, aCallback, aLoadCallback) {
});
}
if ("switchToTabHavingURI" in window) {
if (gUseInContentUI) {
gBrowser.selectedTab = gBrowser.addTab();
switchToTabHavingURI(MANAGER_URI, true, function(aBrowser) {
setup_manager(aBrowser.contentWindow.wrappedJSObject);

View File

@ -20,6 +20,7 @@
# Contributor(s):
# Robert Strong <robert.bugzilla@gmail.com>
# Ehsan Akhgari <ehsan.akhgari@gmail.com>
# Amir Szekely <kichik@gmail.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -111,6 +112,8 @@
!include /NONFATAL WinVer.nsh
!endif
!include x64.nsh
; NSIS provided macros that we have overridden.
!include overrides.nsh
@ -468,21 +471,38 @@
SetOutPath "$R7"
StrCpy $R9 "false"
start:
Pop $R8
StrCmp "$R8" "end" end +1
IfFileExists "$INSTDIR\$R8" +1 start
${While} $R8 != "end"
${Unless} ${FileExists} "$INSTDIR\$R8"
Pop $R8 ; get next file to check before continuing
${Continue}
${EndUnless}
ClearErrors
CopyFiles /SILENT "$INSTDIR\$R8" "$R7\$R8"
IfErrors +4 +1
Delete "$INSTDIR\$R8"
IfErrors +1 start
Delete "$R7\$R8"
ClearErrors
CopyFiles /SILENT "$INSTDIR\$R8" "$R7\$R8" ; try to copy
${If} ${Errors}
; File is in use
StrCpy $R9 "true"
${Break}
${EndIf}
StrCpy $R9 "true"
Delete "$INSTDIR\$R8" ; delete original
${If} ${Errors}
; File is in use
StrCpy $R9 "true"
Delete "$R7\$R8" ; delete temp copy
${Break}
${EndIf}
end:
Pop $R8 ; get next file to check
${EndWhile}
; clear stack
${While} $R8 != "end"
Pop $R8
${EndWhile}
; restore everything
SetOutPath "$INSTDIR"
CopyFiles /SILENT "$R7\*" "$INSTDIR\"
RmDir /r "$R7"
@ -577,9 +597,10 @@
Push $R7
FindWindow $R7 "$R8"
IntCmp $R7 0 +3 +1 +1
MessageBox MB_OK|MB_ICONQUESTION "$R9"
Abort
${If} $R7 <> 0 ; integer comparison
MessageBox MB_OK|MB_ICONQUESTION "$R9"
Abort
${EndIf}
Pop $R7
Exch $R8
@ -665,8 +686,8 @@
FindWindow $R7 "${WindowClass}"
IntCmp $R7 0 +4 +1 +1
System::Call 'user32::PostMessage(i r17, i ${WM_QUIT}, i 0, i 0)'
# The amount of time to wait for the app to shutdown before prompting again
System::Call 'user32::PostMessage(i R7, i ${WM_QUIT}, i 0, i 0)'
; The amount of time to wait for the app to shutdown before prompting again
Sleep 5000
Push $R6
@ -781,12 +802,14 @@
WriteRegStr SHCTX "$R6" "$R7" "$R8"
!ifndef NO_LOG
IfErrors 0 +3
${LogMsg} "** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **"
GoTo +4
StrCmp "$R9" "1" +1 +2
${LogUninstall} "RegVal: $R5 | $R6 | $R7"
${LogMsg} "Added Registry String: $R5 | $R6 | $R7 | $R8"
${If} ${Errors}
${LogMsg} "** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **"
${Else}
${If} $R9 == 1 ; add to the uninstall log?
${LogUninstall} "RegVal: $R5 | $R6 | $R7"
${EndIf}
${LogMsg} "Added Registry String: $R5 | $R6 | $R7 | $R8"
${EndIf}
!endif
Exch $R5
@ -889,12 +912,14 @@
WriteRegDWORD SHCTX "$R6" "$R7" "$R8"
!ifndef NO_LOG
IfErrors 0 +3
${LogMsg} "** ERROR Adding Registry DWord: $R5 | $R6 | $R7 | $R8 **"
GoTo +4
StrCmp "$R9" "1" +1 +2
${LogUninstall} "RegVal: $R5 | $R6 | $R7"
${LogMsg} "Added Registry DWord: $R5 | $R6 | $R7 | $R8"
${If} ${Errors}
${LogMsg} "** ERROR Adding Registry DWord: $R5 | $R6 | $R7 | $R8 **"
${Else}
${If} $R9 == 1 ; add to the uninstall log?
${LogUninstall} "RegVal: $R5 | $R6 | $R7"
${EndIf}
${LogMsg} "Added Registry DWord: $R5 | $R6 | $R7 | $R8"
${EndIf}
!endif
Exch $R5
@ -997,12 +1022,14 @@
WriteRegStr HKCR "$R6" "$R7" "$R8"
!ifndef NO_LOG
IfErrors 0 +3
${LogMsg} "** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **"
GoTo +4
StrCmp "$R9" "1" +1 +2
${LogUninstall} "RegVal: $R5 | $R6 | $R7"
${LogMsg} "Added Registry String: $R5 | $R6 | $R7 | $R8"
${If} ${Errors}
${LogMsg} "** ERROR Adding Registry String: $R5 | $R6 | $R7 | $R8 **"
${Else}
${If} $R9 == 1 ; add to the uninstall log?
${LogUninstall} "RegVal: $R5 | $R6 | $R7"
${EndIf}
${LogMsg} "Added Registry String: $R5 | $R6 | $R7 | $R8"
${EndIf}
!endif
Exch $R5
@ -1059,16 +1086,13 @@
!endif
!macroend
/**
* Creates a registry key. NSIS doesn't supply a RegCreateKey method and instead
* will auto create keys when a reg key name value pair is set.
* i - int (includes char, byte, short, handles, pointers and so on)
* w - wide-char text, string (LPCWSTR, pointer to first character)
* * - pointer specifier -> the proc needs the pointer to type, affects next
* char (parameter) [ex: '*i' - pointer to int]
* see the NSIS documentation for additional information.
*/
!define RegCreateKey "Advapi32::RegCreateKeyW(i, w, *i) i"
!define KEY_SET_VALUE 0x0002
!define KEY_WOW64_64KEY 0x0100
!ifndef HAVE_64BIT_OS
!define CREATE_KEY_SAM ${KEY_SET_VALUE}
!else
!define CREATE_KEY_SAM ${KEY_SET_VALUE}|${KEY_WOW64_64KEY}
!endif
/**
* Creates a registry key. This will log the actions to the install and
@ -1088,8 +1112,8 @@
* located in one of the predefined registry keys this must be closed
* with RegCloseKey (this should not be needed unless someone decides to
* do something extremely squirrelly with NSIS).
* $R5 = return value from RegCreateKeyA (represented by r15 in the system call).
* $R6 = [in] hKey passed to RegCreateKeyA.
* $R5 = return value from RegCreateKeyExW (represented by R5 in the system call).
* $R6 = [in] hKey passed to RegCreateKeyExW.
* $R7 = _ROOT
* $R8 = _KEY
* $R9 = _LOG_UNINSTALL
@ -1119,18 +1143,25 @@
StrCpy $R6 "0x80000002"
; see definition of RegCreateKey
System::Call "${RegCreateKey}($R6, '$R8', .r14) .r15"
System::Call "Advapi32::RegCreateKeyExW(i R6, w R8, i 0, i 0, i 0,\
i ${CREATE_KEY_SAM}, i 0, *i .R4,\
i 0) i .R5"
!ifndef NO_LOG
; if $R5 is not 0 then there was an error creating the registry key.
IntCmp $R5 0 +3 +3
${LogMsg} "** ERROR Adding Registry Key: $R7 | $R8 **"
GoTo +4
StrCmp "$R9" "1" +1 +2
${LogUninstall} "RegKey: $R7 | $R8"
${LogMsg} "Added Registry Key: $R7 | $R8"
${If} $R5 <> 0
${LogMsg} "** ERROR Adding Registry Key: $R7 | $R8 **"
${Else}
${If} $R9 == 1 ; add to the uninstall log?
${LogUninstall} "RegKey: $R7 | $R8"
${EndIf}
${LogMsg} "Added Registry Key: $R7 | $R8"
${EndIf}
!endif
StrCmp $R5 0 +1 +2
System::Call "Advapi32::RegCloseKey(iR4)"
Pop $R4
Pop $R5
Pop $R6
@ -1484,6 +1515,43 @@
!endif
!macroend
################################################################################
# Macros for handling DLL registration
!macro RegisterDLL DLL
; The x64 regsvr32.exe registers x86 DLL's properly on Windows Vista and above
; (not on Windows XP http://support.microsoft.com/kb/282747) so just use it
; when installing on an x64 systems even when installing an x86 application.
${If} ${RunningX64}
${DisableX64FSRedirection}
ExecWait '"$SYSDIR\regsvr32.exe" /s "${DLL}"'
${EnableX64FSRedirection}
${Else}
RegDLL "${DLL}"
${EndIf}
!macroend
!macro UnregisterDLL DLL
; The x64 regsvr32.exe registers x86 DLL's properly on Windows Vista and above
; (not on Windows XP http://support.microsoft.com/kb/282747) so just use it
; when installing on an x64 systems even when installing an x86 application.
${If} ${RunningX64}
${DisableX64FSRedirection}
ExecWait '"$SYSDIR\regsvr32.exe" /s /u "${DLL}"'
${EnableX64FSRedirection}
${Else}
UnRegDLL "${DLL}"
${EndIf}
!macroend
!define RegisterDLL `!insertmacro RegisterDLL`
!define UnregisterDLL `!insertmacro UnregisterDLL`
################################################################################
# Macros for retrieving existing install paths
@ -1781,20 +1849,31 @@
; UNC path so always try to create $INSTDIR
CreateDirectory "$INSTDIR\"
GetTempFileName $R8 "$INSTDIR\"
IfFileExists "$R8" +3 +1 ; Can files be created?
StrCpy $R9 "false"
Goto +12
Delete "$R8"
IfFileExists "$R8" +1 +3 ; Can files be deleted?
StrCpy $R9 "false"
Goto +8
CreateDirectory "$R8"
IfFileExists "$R8" +3 +1 ; Can directories be created?
StrCpy $R9 "false"
GoTo +4
RmDir "$R8"
IfFileExists "$R8" +1 +2 ; Can directories be deleted?
StrCpy $R9 "false"
${Unless} ${FileExists} $R8 ; Can files be created?
StrCpy $R9 "false"
Goto done
${EndUnless}
Delete $R8
${If} ${FileExists} $R8 ; Can files be deleted?
StrCpy $R9 "false"
Goto done
${EndIf}
CreateDirectory $R8
${Unless} ${FileExists} $R8 ; Can directories be created?
StrCpy $R9 "false"
Goto done
${EndUnless}
RmDir $R8
${If} ${FileExists} $R8 ; Can directories be deleted?
StrCpy $R9 "false"
Goto done
${EndIf}
done:
RmDir "$INSTDIR\" ; Only remove $INSTDIR if it is empty
ClearErrors
@ -1843,7 +1922,7 @@
* directory using GetDiskFreeSpaceExW which respects disk quotas. This macro
* will calculate the size of all sections that are selected, compare that with
* the free space available, and if there is sufficient free space it will
* return true... if not, it will return false.
* return true... if not, it will return false.
*
* @return _RESULT
* "true" if there is sufficient free space otherwise "false".
@ -1902,7 +1981,7 @@
Delete "$R7"
CreateDirectory "$R7"
System::Call 'kernel32::GetDiskFreeSpaceExW(w, *l, *l, *l) i(r17, .r16, ., .) .'
System::Call 'kernel32::GetDiskFreeSpaceExW(w, *l, *l, *l) i(R7, .R6, ., .) .'
; Convert to KB for comparison with $R8 which is in KB
System::Int64Op $R6 / 1024
@ -2199,7 +2278,7 @@
GetFullPathName $R8 "$R9"
IfErrors end_GetLongPath +1 ; If the path doesn't exist return an empty string.
System::Call 'kernel32::GetLongPathNameW(w r18, w .r17, i 1024)i .r16'
System::Call 'kernel32::GetLongPathNameW(w R8, w .R7, i 1024)i .R6'
StrCmp "$R7" "" +4 +1 ; Empty string when GetLongPathNameW is not present.
StrCmp $R6 0 +3 +1 ; Should never equal 0 since the path exists.
StrCpy $R9 "$R7"
@ -2307,6 +2386,9 @@
* to this reg cleanup since the referenced key would be for an app that is no
* longer installed on the system.
*
* $R0 = on x64 systems set to 'false' at the beginning of the macro when
* enumerating the x86 registry view and set to 'true' when enumerating
* the x64 registry view.
* $R1 = stores the long path to $INSTDIR
* $R2 = return value from the stack from the GetParent and GetLongPath macros
* $R3 = return value from the outer loop's EnumRegKey
@ -2342,10 +2424,23 @@
Push $R3
Push $R2
Push $R1
Push $R0
${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R1
StrCpy $R6 0 ; set the counter for the outer loop to 0
${If} ${RunningX64}
StrCpy $R0 "false"
; Set the registry to the 32 bit registry for 64 bit installations or to
; the 64 bit registry for 32 bit installations at the beginning so it can
; easily be set back to the correct registry view when finished.
!ifdef HAVE_64BIT_OS
SetRegView 32
!else
SetRegView 64
!endif
${EndIf}
outerloop:
EnumRegKey $R3 SHCTX $R9 $R6
StrCmp $R3 "" end +1 ; if empty there are no more keys to enumerate
@ -2393,8 +2488,23 @@
GoTo outerloop
end:
${If} ${RunningX64}
${AndIf} "$R0" == "false"
; Set the registry to the correct view.
!ifdef HAVE_64BIT_OS
SetRegView 64
!else
SetRegView 32
!endif
StrCpy $R6 0 ; set the counter for the outer loop to 0
StrCpy $R0 "true"
GoTo outerloop
${EndIf}
ClearErrors
Pop $R0
Pop $R1
Pop $R2
Pop $R3
@ -2443,9 +2553,13 @@
/**
* Removes all registry keys from \Software\Windows\CurrentVersion\Uninstall
* that reference this install location. This uses SHCTX to determine the
* registry hive so you must call SetShellVarContext first.
* that reference this install location in both the 32 bit and 64 bit registry
* view. This macro uses SHCTX to determine the registry hive so you must call
* SetShellVarContext first.
*
* $R3 = on x64 systems set to 'false' at the beginning of the macro when
* enumerating the x86 registry view and set to 'true' when enumerating
* the x64 registry view.
* $R4 = stores the long path to $INSTDIR
* $R5 = return value from ReadRegStr
* $R6 = string for the base reg key (e.g. Software\Microsoft\Windows\CurrentVersion\Uninstall)
@ -2474,12 +2588,25 @@
Push $R6
Push $R5
Push $R4
Push $R3
${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R4
StrCpy $R6 "Software\Microsoft\Windows\CurrentVersion\Uninstall"
StrCpy $R7 ""
StrCpy $R8 0
${If} ${RunningX64}
StrCpy $R3 "false"
; Set the registry to the 32 bit registry for 64 bit installations or to
; the 64 bit registry for 32 bit installations at the beginning so it can
; easily be set back to the correct registry view when finished.
!ifdef HAVE_64BIT_OS
SetRegView 32
!else
SetRegView 64
!endif
${EndIf}
loop:
EnumRegKey $R7 SHCTX $R6 $R8
StrCmp $R7 "" end +1
@ -2492,13 +2619,29 @@
StrCmp "$R9" "$R4" +1 loop
ClearErrors
DeleteRegKey SHCTX "$R6\$R7"
IfErrors loop
IfErrors loop +1
IntOp $R8 $R8 - 1 ; Decrement the counter on successful deletion
GoTo loop
end:
${If} ${RunningX64}
${AndIf} "$R3" == "false"
; Set the registry to the correct view.
!ifdef HAVE_64BIT_OS
SetRegView 64
!else
SetRegView 32
!endif
StrCpy $R7 ""
StrCpy $R8 0
StrCpy $R3 "true"
GoTo loop
${EndIf}
ClearErrors
Pop $R3
Pop $R4
Pop $R5
Pop $R6
@ -2838,15 +2981,16 @@
StrCpy $R8 "$R9"
StrCpy $R9 "false"
ReadRegStr $R7 SHCTX "Software\Classes\$R8\shell\open\command" ""
StrCmp "$R7" "" end
${GetPathFromString} "$R7" $R7
${GetParent} "$R7" $R7
${GetLongPath} "$R7" $R7
StrCmp "$R7" "$INSTDIR" +1 end
StrCpy $R9 "true"
${If} $R7 != ""
${GetPathFromString} "$R7" $R7
${GetParent} "$R7" $R7
${GetLongPath} "$R7" $R7
${If} $R7 == $INSTDIR
StrCpy $R9 "true"
${EndIf}
${EndIf}
end:
ClearErrors
Pop $R7
@ -2892,14 +3036,14 @@
!macroend
/**
* If present removes the VirtualStore directory for this installation. Uses the
* program files directory path and the current install location to determine
* the sub-directory in the VirtualStore directory.
* Removes the application's VirtualStore directory if present when the
* installation directory is a sub-directory of the program files directory.
*
* $R4 = $PROGRAMFILES/$PROGRAMFILES64 for CleanVirtualStore_Internal
* $R5 = various path values.
* $R6 = length of the long path to $PROGRAMFILES
* $R7 = length of the long path to $INSTDIR
* $R8 = long path to $PROGRAMFILES
* $R6 = length of the long path to $PROGRAMFILES32 or $PROGRAMFILES64
* $R7 = long path to $PROGRAMFILES32 or $PROGRAMFILES64
* $R8 = length of the long path to $INSTDIR
* $R9 = long path to $INSTDIR
*/
!macro CleanVirtualStore
@ -2921,34 +3065,25 @@
Push $R7
Push $R6
Push $R5
Push $R4
${${_MOZFUNC_UN}GetLongPath} "$INSTDIR" $R9
StrCmp $R9 "" end +1
${${_MOZFUNC_UN}GetLongPath} "$PROGRAMFILES" $R8
StrCmp $R8 "" end +1
${If} "$R9" != ""
StrLen $R8 "$R9"
StrLen $R7 "$R9"
StrLen $R6 "$R8"
; Only continue If the length of $INSTDIR is greater than the length of
; $PROGRAMFILES
IntCmp $R7 $R6 end end +1
StrCpy $R4 $PROGRAMFILES32
Call ${_MOZFUNC_UN}CleanVirtualStore_Internal
; Copy from the start of $INSTDIR the length of $PROGRAMFILES
StrCpy $R5 "$R9" $R6
StrCmp "$R5" "$R8" +1 end ; Check if $INSTDIR is under $PROGRAMFILES
${If} ${RunningX64}
StrCpy $R4 $PROGRAMFILES64
Call ${_MOZFUNC_UN}CleanVirtualStore_Internal
${EndIf}
; Remove the drive letter and colon from the $INSTDIR long path
StrCpy $R5 "$R9" "" 2
StrCpy $R5 "$PROFILE\AppData\Local\VirtualStore$R5"
${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
StrCmp $R5 "" end +1
${EndIf}
IfFileExists "$R5" +1 end
RmDir /r "$R5"
end:
ClearErrors
Pop $R4
Pop $R5
Pop $R6
Pop $R7
@ -2956,6 +3091,27 @@
Pop $R9
FunctionEnd
Function ${_MOZFUNC_UN}CleanVirtualStore_Internal
${${_MOZFUNC_UN}GetLongPath} "" $R7
${If} "$R7" != ""
StrLen $R6 "$R7"
${If} $R8 < $R6
; Copy from the start of $INSTDIR the length of $PROGRAMFILES64
StrCpy $R5 "$R9" $R6
${If} "$R5" == "$R7"
; Remove the drive letter and colon from the $INSTDIR long path
StrCpy $R5 "$R9" "" 2
StrCpy $R5 "$LOCALAPPDATA\VirtualStore$R5"
${${_MOZFUNC_UN}GetLongPath} "$R5" $R5
${If} "$R5" != ""
${AndIf} ${FileExists} "$R5"
RmDir /r "$R5"
${EndIf}
${EndIf}
${EndIf}
${EndIf}
FunctionEnd
!verbose pop
!endif
!macroend
@ -3036,7 +3192,7 @@
; $PROGRAMFILES
IntCmp $R6 $R5 end end +1
; Copy from the start of $INSTDIR the length of $PROGRAMFILES
; Copy from the start of $INSTDIR the length of $PROGRAMFILES
StrCpy $R4 "$R8" $R5
StrCmp "$R4" "$R7" +1 end ; Check if $INSTDIR is under $PROGRAMFILES
@ -3430,21 +3586,20 @@
ClearErrors
GetFullPathName $R3 "$INSTDIR\uninstall"
IfFileExists "$R3\uninstall.update" +1 end_UpdateUninstallLog
${If} ${FileExists} "$R3\uninstall.update"
${LineFind} "$R3\uninstall.update" "" "1:-1" "CleanupUpdateLog"
${LineFind} "$R3\uninstall.update" "" "1:-1" "CleanupUpdateLog"
GetTempFileName $R2 "$R3"
FileOpen $R1 "$R2" w
${TextCompareNoDetails} "$R3\uninstall.update" "$R3\uninstall.log" "SlowDiff" "CreateUpdateDiff"
FileClose $R1
GetTempFileName $R2 "$R3"
FileOpen $R1 "$R2" w
${TextCompareNoDetails} "$R3\uninstall.update" "$R3\uninstall.log" "SlowDiff" "CreateUpdateDiff"
FileClose $R1
IfErrors +2 0
${FileJoin} "$R3\uninstall.log" "$R2" "$R3\uninstall.log"
IfErrors +2 0
${FileJoin} "$R3\uninstall.log" "$R2" "$R3\uninstall.log"
${DeleteFile} "$R2"
${EndIf}
${DeleteFile} "$R2"
end_UpdateUninstallLog:
ClearErrors
Pop $R0
@ -3491,8 +3646,9 @@
Function CreateUpdateDiff
${TrimNewLines} "$9" $9
StrCmp $9 "" +2 +1
FileWrite $R1 "$9$\r$\n"
${If} $9 != ""
FileWrite $R1 "$9$\r$\n"
${EndIf}
Push 0
FunctionEnd
@ -3764,24 +3920,27 @@
ClearErrors
Delete "$R1"
IfErrors +3 +1
${LogMsg} "Deleted File: $R1"
GoTo end
${Unless} ${Errors}
${LogMsg} "Deleted File: $R1"
Goto end
${EndUnless}
ClearErrors
Rename "$R1" "$R1.moz-delete"
IfErrors +4 +1
Delete /REBOOTOK "$R1.moz-delete"
${LogMsg} "Delayed Delete File (Reboot Required): $R1.moz-delete"
GoTo end
${Unless} ${Errors}
Delete /REBOOTOK "$R1.moz-delete"
${LogMsg} "Delayed Delete File (Reboot Required): $R1.moz-delete"
GoTo end
${EndUnless}
; Check if the file exists in the source. If it does the new file will
; replace the existing file when the system is rebooted. If it doesn't
; the file will be deleted when the system is rebooted.
IfFileExists "$EXEDIR\core$R9" end +1
IfFileExists "$EXEDIR\optional$R9" end +1
Delete /REBOOTOK "$R1"
${LogMsg} "Delayed Delete File (Reboot Required): $R1"
${Unless} ${FileExists} "$EXEDIR\core$R9"
${AndUnless} ${FileExists} "$EXEDIR\optional$R9"
Delete /REBOOTOK "$R1"
${LogMsg} "Delayed Delete File (Reboot Required): $R1"
${EndUnless}
end:
ClearErrors
@ -3937,7 +4096,7 @@
StrCmp $R0 "\" +2 +1
StrCpy $R1 "$R9"
UnRegDLL $R1
${UnregisterDLL} $R1
end:
ClearErrors
@ -4030,10 +4189,9 @@
Push $R0
StrCpy $R3 ""
IfFileExists "$INSTDIR\uninstall\uninstall.log" +1 end_FindSMProgramsDir
${LineFind} "$INSTDIR\uninstall\uninstall.log" "/NUL" "1:-1" "FindSMProgramsDirRelPath"
end_FindSMProgramsDir:
${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
${LineFind} "$INSTDIR\uninstall\uninstall.log" "/NUL" "1:-1" "FindSMProgramsDirRelPath"
${EndIf}
ClearErrors
Pop $R0
@ -4406,24 +4564,35 @@
Push $R6
Push $R5
${Unless} ${AtLeastWin2000}
; XXX-rstrong - some systems fail the AtLeastWin2000 test for an
; unknown reason. To work around this also check if the Windows NT
; registry Key exists and if it does if the first char in
; CurrentVersion is equal to 3 (Windows NT 3.5 and 3.5.1) or 4
; (Windows NT 4).
StrCpy $R8 ""
ClearErrors
ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion"
StrCpy $R8 "$R8" 1
${If} ${Errors}
${OrIf} "$R8" == "3"
${OrIf} "$R8" == "4"
!ifdef HAVE_64BIT_OS
${Unless} ${RunningX64}
${OrUnless} ${AtLeastWinVista}
MessageBox MB_OK|MB_ICONSTOP "$R9" IDOK
; Nothing initialized so no need to call OnEndCommon
Quit
${EndIf}
${EndUnless}
${EndUnless}
SetRegView 64
!else
${Unless} ${AtLeastWin2000}
; XXX-rstrong - some systems fail the AtLeastWin2000 test for an
; unknown reason. To work around this also check if the Windows NT
; registry Key exists and if it does if the first char in
; CurrentVersion is equal to 3 (Windows NT 3.5 and 3.5.1) or 4
; (Windows NT 4).
StrCpy $R8 ""
ClearErrors
ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion"
StrCpy $R8 "$R8" 1
${If} ${Errors}
${OrIf} "$R8" == "3"
${OrIf} "$R8" == "4"
MessageBox MB_OK|MB_ICONSTOP "$R9" IDOK
; Nothing initialized so no need to call OnEndCommon
Quit
${EndIf}
${EndUnless}
!endif
${GetParameters} $R8
@ -4445,7 +4614,11 @@
SetSilent silent
ReadINIStr $R8 $R7 "Install" "InstallDirectoryName"
${If} $R8 != ""
StrCpy $INSTDIR "$PROGRAMFILES\$R8"
!ifdef HAVE_64BIT_OS
StrCpy $INSTDIR "$PROGRAMFILES64\$R8"
!else
StrCpy $INSTDIR "$PROGRAMFILES32\$R8"
!endif
${Else}
ReadINIStr $R8 $R7 "Install" "InstallDirectoryPath"
${If} $R8 != ""
@ -4459,11 +4632,19 @@
StrCpy $R6 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${AppVersion})"
ReadRegStr $R8 HKLM "$R6" "InstallLocation"
${If} $R8 == ""
StrCpy $INSTDIR "$PROGRAMFILES\${BrandFullName}"
!ifdef HAVE_64BIT_OS
StrCpy $INSTDIR "$PROGRAMFILES64\${BrandFullName}"
!else
StrCpy $INSTDIR "$PROGRAMFILES32\${BrandFullName}"
!endif
${Else}
GetFullPathName $INSTDIR "$R8"
${Unless} ${FileExists} "$INSTDIR"
StrCpy $INSTDIR "$PROGRAMFILES\${BrandFullName}"
!ifdef HAVE_64BIT_OS
StrCpy $INSTDIR "$PROGRAMFILES64\${BrandFullName}"
!else
StrCpy $INSTDIR "$PROGRAMFILES32\${BrandFullName}"
!endif
${EndUnless}
${EndIf}
${EndIf}
@ -4589,10 +4770,10 @@
!define UninstallOnInitCommon "!insertmacro UninstallOnInitCommonCall"
Function UninstallOnInitCommon
; Prevents breaking apps that don't use SetBrandNameVars
!ifdef SetBrandNameVars
${SetBrandNameVars} "$EXEDIR\distribution\setup.ini"
!endif
; Prevents breaking apps that don't use SetBrandNameVars
!ifdef SetBrandNameVars
${SetBrandNameVars} "$EXEDIR\distribution\setup.ini"
!endif
; Prevent launching the application when a reboot is required and this
; executable is the main application executable
@ -4606,10 +4787,10 @@
IfFileExists "$INSTDIR\${FileMainEXE}" +2 +1
Quit ; Nothing initialized so no need to call OnEndCommon
; Prevents breaking apps that don't use SetBrandNameVars
!ifdef SetBrandNameVars
${SetBrandNameVars} "$INSTDIR\distribution\setup.ini"
!endif
; Prevents breaking apps that don't use SetBrandNameVars
!ifdef SetBrandNameVars
${SetBrandNameVars} "$INSTDIR\distribution\setup.ini"
!endif
; Prevent all operations (e.g. set as default, postupdate, etc.) when a
; reboot is required and the executable launched is helper.exe
@ -4618,6 +4799,10 @@
Reboot
Quit ; Nothing initialized so no need to call OnEndCommon
!ifdef HAVE_64BIT_OS
SetRegView 64
!endif
${GetParameters} $R0
StrCmp "$R0" "" continue +1
@ -4718,8 +4903,9 @@
WriteUninstaller "$EXEDIR\uninstaller.exe"
StrCpy $R1 "$\"$EXEDIR\uninstaller.exe$\""
StrCmp $R0 "/S" +1 +2
StrCpy $R1 "$\"$EXEDIR\uninstaller.exe$\" /S"
${If} ${Silent}
StrCpy $R1 "$\"$EXEDIR\uninstaller.exe$\" /S"
${EndIf}
; When the uninstaller is launched it copies itself to the temp directory
; so it won't be in use so it can delete itself.
@ -4742,6 +4928,53 @@
!verbose pop
!macroend
/**
* Called from the uninstaller's un.onInit function not to be confused with the
* installer's .onInit or the uninstaller's .onInit functions.
*/
!macro un.UninstallUnOnInitCommon
!ifndef un.UninstallUnOnInitCommon
!insertmacro un.GetLongPath
!insertmacro un.GetParent
!insertmacro un.SetBrandNameVars
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
!define un.UninstallUnOnInitCommon "!insertmacro un.UninstallUnOnInitCommonCall"
Function un.UninstallUnOnInitCommon
${un.GetParent} "$INSTDIR" $INSTDIR
${un.GetLongPath} "$INSTDIR" $INSTDIR
${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}"
Abort
${EndUnless}
!ifdef HAVE_64BIT_OS
SetRegView 64
!endif
; Prevents breaking apps that don't use SetBrandNameVars
!ifdef un.SetBrandNameVars
${un.SetBrandNameVars} "$INSTDIR\distribution\setup.ini"
!endif
; Initialize $hHeaderBitmap to prevent redundant changing of the bitmap if
; the user clicks the back button
StrCpy $hHeaderBitmap ""
FunctionEnd
!verbose pop
!endif
!macroend
!macro un.UninstallUnOnInitCommonCall
!verbose push
!verbose ${_MOZFUNC_VERBOSE}
Call un.UninstallUnOnInitCommon
!verbose pop
!macroend
/**
* Called from the MUI leaveOptions function to set the value of $INSTDIR.
*/
@ -4891,14 +5124,16 @@
Push $R7
${CanWriteToInstallDir} $R7
StrCmp $R7 "false" +1 +3
MessageBox MB_OK|MB_ICONEXCLAMATION "$R9"
Abort
${If} $R7 == "false"
MessageBox MB_OK|MB_ICONEXCLAMATION "$R9"
Abort
${EndIf}
${CheckDiskSpace} $R7
StrCmp $R7 "false" +1 +3
MessageBox MB_OK|MB_ICONEXCLAMATION "$R8"
Abort
${If} $R7 == "false"
MessageBox MB_OK|MB_ICONEXCLAMATION "$R8"
Abort
${EndIf}
Pop $R7
Exch $R8
@ -4951,12 +5186,13 @@
RmDir /r "$INSTDIR\distribution"
; Remove files from the uninstall directory.
IfFileExists "$INSTDIR\uninstall" +1 +7
Delete "$INSTDIR\uninstall\*wizard*"
Delete "$INSTDIR\uninstall\uninstall.ini"
Delete "$INSTDIR\uninstall\cleanup.log"
Delete "$INSTDIR\uninstall\uninstall.update"
${OnInstallUninstall}
${If} ${FileExists} "$INSTDIR\uninstall"
Delete "$INSTDIR\uninstall\*wizard*"
Delete "$INSTDIR\uninstall\uninstall.ini"
Delete "$INSTDIR\uninstall\cleanup.log"
Delete "$INSTDIR\uninstall\uninstall.update"
${OnInstallUninstall}
${EndIf}
; Since we write to the uninstall.log in this directory during the
; installation create the directory if it doesn't already exist.
@ -5064,7 +5300,7 @@
; the UAC plugin to use UAC::ExecCodeSegment to execute code in
; the non-elevated context.
${Unless} ${Errors}
UAC::RunElevated
UAC::RunElevated
${EndUnless}
${EndIf}
${EndIf}
@ -5117,7 +5353,7 @@
; plugin to use UAC::ExecCodeSegment to execute code in the
; non-elevated context.
${Unless} ${Errors}
UAC::RunElevated
UAC::RunElevated
${EndUnless}
${EndIf}
${EndIf}
@ -5330,6 +5566,12 @@
${LogMsg} "OS Name : Unable to detect"
${EndIf}
!ifdef HAVE_64BIT_OS
${LogMsg} "Target CPU : x64"
!else
${LogMsg} "Target CPU : x86"
!endif
Pop $9
Pop $R0
Pop $R1
@ -5551,7 +5793,7 @@
* @param _SECTION_NAME
* The section name to write to in the shortcut log ini file
* @param _FILE_NAME
* The
* The shortcut's file name
*
* $R6 = return value from ReadIniStr for the shortcut file name
* $R7 = counter for supporting multiple shortcuts in the same location
@ -5741,7 +5983,8 @@
* to the shortcuts log ini file.
*
* @param _REL_PATH_TO_DIR
* The
* The relative path from the Start Menu Programs directory to the
* program's directory.
*
* $R9 = _REL_PATH_TO_DIR
*/
@ -5843,12 +6086,12 @@
; the categories will be removed by the second call to
; WSCSetApplicationCategory.
StrCmp "$R9" "0x00000000" +2 +1
System::Call "Ws2_32::WSCSetApplicationCategory(w r18, i r17, w n, i 0,\
System::Call "Ws2_32::WSCSetApplicationCategory(w R8, i R7, w n, i 0,\
i 0x00000000, i n, *i) i"
; Set the permitted LSP categories
System::Call "Ws2_32::WSCSetApplicationCategory(w r18, i r17, w n, i 0,\
i r19, i n, *i .s) i.r16"
System::Call "Ws2_32::WSCSetApplicationCategory(w R8, i R7, w n, i 0,\
i R9, i n, *i .s) i.R6"
Pop $R5
!ifndef NO_LOG
@ -5923,9 +6166,9 @@
ClearErrors
; stack: path, appid
Exch $R9 ; stack: $R9, appid | $R9 = path
Exch $R9 ; stack: $R9, appid | $R9 = path
Exch 1 ; stack: appid, $R9
Exch $R8 ; stack: $R8, $R9 | $R8 = appid
Exch $R8 ; stack: $R8, $R9 | $R8 = appid
Push $R7 ; stack: $R7, $R8, $R9
Push $R6
Push $R5

View File

@ -1579,9 +1579,6 @@ var gErrorsPage = {
gUpdates.setButtons(null, null, "okButton", true);
gUpdates.wiz.getButton("finish").focus();
var errorsTitle = gUpdates.getAUSString("errorsPageHeader");
document.getElementById("errorsHeader").setAttribute("label", errorsTitle);
var statusText = gUpdates.update.statusText;
LOG("gErrorsPage" , "onPageShow - update.statusText: " + statusText);

View File

@ -215,7 +215,7 @@
<wizardpage id="errors" pageid="errors" object="gErrorsPage"
onpageshow="gErrorsPage.onPageShow();">
<updateheader id="errorsHeader" label=""/>
<updateheader label="&error.title;"/>
<vbox class="update-content" flex="1">
<label id="errorIntro">&error.label;</label>
<separator/>
@ -233,7 +233,7 @@
<wizardpage id="errorpatching" pageid="errorpatching" next="downloading"
object="gErrorPatchingPage"
onpageshow="gErrorPatchingPage.onPageShow();">
<updateheader label="&errorpatching.title;"/>
<updateheader label="&error.title;"/>
<vbox class="update-content" flex="1">
<label>&errorpatching.intro;</label>
</vbox>

View File

@ -46,6 +46,42 @@
-moz-border-radius: 5px;
}
.nav-button {
-moz-appearance: toolbarbutton;
min-width: 0;
}
#back-btn:-moz-locale-dir(ltr) {
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=toolbar");
}
#forward-btn:-moz-locale-dir(ltr) {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar");
}
#back-btn:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=toolbar");
}
#forward-btn:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar");
}
#back-btn[disabled="true"]:-moz-locale-dir(ltr) {
list-style-image: url("moz-icon://stock/gtk-go-back-ltr?size=toolbar&state=disabled");
}
#forward-btn[disabled="true"]:-moz-locale-dir(ltr) {
list-style-image: url("moz-icon://stock/gtk-go-forward-ltr?size=toolbar&state=disabled");
}
#back-btn[disabled="true"]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-back-rtl?size=toolbar&state=disabled");
}
#forward-btn[disabled="true"]:-moz-locale-dir(rtl) {
list-style-image: url("moz-icon://stock/gtk-go-forward-rtl?size=toolbar&state=disabled");
}
/*** category selector ***/
@ -155,7 +191,6 @@
#header {
margin-bottom: 20px;
height: 2em;
}
#header-name, #header-link {

View File

@ -35,6 +35,8 @@
*
* ***** END LICENSE BLOCK ***** */
%include ../../global/shared.inc
#addons-page {
background-color: #c5ccd7;
-moz-appearance: none;
@ -47,6 +49,52 @@
-moz-border-radius: 5px;
}
.nav-button {
-moz-appearance: none;
min-width: 0;
padding: 0 4px;
margin: 0;
text-shadow: @loweredShadow@;
border: 1px solid @toolbarbuttonBorderColor@;
-moz-box-shadow: @loweredShadow@;
background: @toolbarbuttonBackground@;
background-origin: border-box;
list-style-image: url(chrome://mozapps/skin/extensions/navigation.png);
}
.nav-button .button-text {
display: none;
}
.nav-button[disabled="true"] .button-icon {
opacity: 0.4;
}
#back-btn:-moz-locale-dir(ltr),
#forward-btn:-moz-locale-dir(rtl) {
-moz-border-radius-topleft: @toolbarbuttonCornerRadius@;
-moz-border-radius-bottomleft: @toolbarbuttonCornerRadius@;
border-right: none;
-moz-image-region: rect(0, 20px, 20px, 0);
}
#back-btn:-moz-locale-dir(rtl),
#forward-btn:-moz-locale-dir(ltr) {
-moz-border-radius-topright: @toolbarbuttonCornerRadius@;
-moz-border-radius-bottomright: @toolbarbuttonCornerRadius@;
-moz-image-region: rect(0, 40px, 20px, 20px);
}
.nav-button:hover:active:not([disabled="true"]) {
background: @toolbarbuttonPressedBackgroundColor@;
text-shadow: @loweredShadow@;
-moz-box-shadow: @toolbarbuttonPressedInnerShadow@, @loweredShadow@;
}
.nav-button:-moz-window-inactive {
border-color: @toolbarbuttonInactiveBorderColor@;
background-image: @toolbarbuttonInactiveBackgroundImage@;
}
/*** category selector ***/
@ -156,7 +204,6 @@
#header {
margin-bottom: 20px;
height: 2em;
}
#header-name, #header-link {

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

View File

@ -26,8 +26,9 @@ toolkit.jar:
skin/classic/mozapps/extensions/cancel.png (extensions/cancel.png)
skin/classic/mozapps/extensions/pause.png (extensions/pause.png)
skin/classic/mozapps/extensions/utilities.png (extensions/utilities.png)
skin/classic/mozapps/extensions/navigation.png (extensions/navigation.png)
skin/classic/mozapps/extensions/about.css (extensions/about.css)
skin/classic/mozapps/extensions/extensions.css (extensions/extensions.css)
* skin/classic/mozapps/extensions/extensions.css (extensions/extensions.css)
skin/classic/mozapps/extensions/update.css (extensions/update.css)
skin/classic/mozapps/extensions/eula.css (extensions/eula.css)
skin/classic/mozapps/extensions/blocklist.css (extensions/blocklist.css)

View File

@ -47,6 +47,21 @@
-moz-border-radius: 5px;
}
.nav-button {
list-style-image: url(chrome://mozapps/skin/extensions/navigation.png);
min-width: 0;
-moz-margin-end: 0;
}
#back-btn:-moz-locale-dir(ltr),
#forward-btn:-moz-locale-dir(rtl) {
-moz-image-region: rect(0, 18px, 18px, 0);
}
#back-btn:-moz-locale-dir(rtl),
#forward-btn:-moz-locale-dir(ltr) {
-moz-image-region: rect(0, 36px, 18px, 18px);
}
/*** category selector ***/
@ -156,7 +171,6 @@
#header {
margin-bottom: 20px;
height: 2em;
}
#header-name, #header-link {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -32,6 +32,7 @@ toolkit.jar:
skin/classic/mozapps/extensions/cancel.png (extensions/cancel.png)
skin/classic/mozapps/extensions/pause.png (extensions/pause.png)
skin/classic/mozapps/extensions/utilities.png (extensions/utilities.png)
skin/classic/mozapps/extensions/navigation.png (extensions/navigation.png)
skin/classic/mozapps/extensions/eula.css (extensions/eula.css)
skin/classic/mozapps/handling/handling.css (handling/handling.css)
skin/classic/mozapps/passwordmgr/key.png (passwordmgr/key.png)
@ -95,6 +96,7 @@ toolkit.jar:
skin/classic/aero/mozapps/extensions/cancel.png (extensions/cancel.png)
skin/classic/aero/mozapps/extensions/pause.png (extensions/pause.png)
skin/classic/aero/mozapps/extensions/utilities.png (extensions/utilities.png)
skin/classic/aero/mozapps/extensions/navigation.png (extensions/navigation.png)
skin/classic/aero/mozapps/extensions/eula.css (extensions/eula.css)
skin/classic/aero/mozapps/handling/handling.css (handling/handling.css)
skin/classic/aero/mozapps/passwordmgr/key.png (passwordmgr/key-aero.png)

View File

@ -112,6 +112,7 @@ XPIDLSRCS = \
nsIPrintSettingsService.idl \
nsIPrintOptions.idl \
nsIIdleService.idl \
nsIGfxInfo.idl \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
@ -126,7 +127,6 @@ XPIDLSRCS += nsIPrintSettingsWin.idl \
nsITaskbarPreviewButton.idl \
nsIJumpListBuilder.idl \
nsIJumpListItem.idl \
nsIGfxInfo.idl \
$(NULL)
endif

View File

@ -66,6 +66,5 @@ interface nsIGfxInfo : nsISupports
readonly attribute DOMString adapterDriverVersion;
readonly attribute DOMString adapterDriverDate;
};

View File

@ -54,6 +54,8 @@ using namespace mozilla::widget;
NS_IMPL_ISUPPORTS1(GfxInfo, nsIGfxInfo)
/* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after gfxPlatform initialization
* has occurred because they depend on it for information. (See bug 591561) */
nsresult GfxInfo::GetD2DEnabled(PRBool *aEnabled)
{
*aEnabled = gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
@ -68,13 +70,12 @@ nsresult GfxInfo::GetDWriteEnabled(PRBool *aEnabled)
/* XXX: GfxInfo doesn't handle multiple GPUs. We should try to do that. Bug #591057 */
static nsresult GetKeyValue(const TCHAR* keyLocation, const TCHAR* keyName, nsAString& destString, int type)
static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName, nsAString& destString, int type)
{
HKEY key;
DWORD dwcbData;
WCHAR wCharValue[1024];
TCHAR tCharValue[1024];
DWORD dValue;
DWORD resultType;
LONG result;
nsresult retval = NS_OK;
@ -87,27 +88,47 @@ static nsresult GetKeyValue(const TCHAR* keyLocation, const TCHAR* keyName, nsAS
case REG_DWORD: {
// We only use this for vram size
dwcbData = sizeof(dValue);
result = RegQueryValueExW(key, keyName, NULL, NULL, (LPBYTE)&dValue, &dwcbData);
if (result != ERROR_SUCCESS) {
result = RegQueryValueExW(key, keyName, NULL, &resultType, (LPBYTE)&dValue, &dwcbData);
if (result == ERROR_SUCCESS && resultType == REG_DWORD) {
dValue = dValue / 1024 / 1024;
destString.AppendInt(static_cast<PRInt32>(dValue));
} else {
retval = NS_ERROR_FAILURE;
}
dValue = dValue / 1024 / 1024;
destString.AppendInt(static_cast<PRInt32>(dValue));
break;
}
case REG_MULTI_SZ: {
// A chain of null-separated strings; we convert the nulls to spaces
dwcbData = sizeof(tCharValue);
result = RegQueryValueExW(key, keyName, NULL, NULL, (LPBYTE)tCharValue, &dwcbData);
if (result != ERROR_SUCCESS) {
WCHAR wCharValue[1024];
dwcbData = sizeof(wCharValue);
result = RegQueryValueExW(key, keyName, NULL, &resultType, (LPBYTE)wCharValue, &dwcbData);
if (result == ERROR_SUCCESS && resultType == REG_MULTI_SZ) {
// This bit here could probably be cleaner.
bool isValid = false;
DWORD strLen = dwcbData/sizeof(wCharValue[0]);
for (DWORD i = 0; i < strLen; i++) {
if (wCharValue[i] == '\0') {
if (i < strLen - 1 && wCharValue[i + 1] == '\0') {
isValid = true;
break;
} else {
wCharValue[i] = ' ';
}
}
}
// ensure wCharValue is null terminated
wCharValue[strLen-1] = '\0';
if (isValid)
destString = wCharValue;
} else {
retval = NS_ERROR_FAILURE;
}
// This bit here could probably be cleaner.
for (DWORD i = 0, len = dwcbData/sizeof(tCharValue[0]); i < len; i++) {
if (tCharValue[i] == '\0')
tCharValue[i] = ' ';
}
destString = tCharValue;
break;
}
}
@ -140,44 +161,40 @@ void GfxInfo::Init()
{
NS_TIME_FUNCTION;
DISPLAY_DEVICE lpDisplayDevice;
lpDisplayDevice.cb = sizeof(lpDisplayDevice);
DISPLAY_DEVICEW displayDevice;
displayDevice.cb = sizeof(displayDevice);
int deviceIndex = 0;
while (EnumDisplayDevices(NULL, deviceIndex, &lpDisplayDevice, 0)) {
if (lpDisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
while (EnumDisplayDevicesW(NULL, deviceIndex, &displayDevice, 0)) {
if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
break;
deviceIndex++;
}
/* DeviceKey is "reserved" according to MSDN so we'll be careful with it */
if (wcsncmp(lpDisplayDevice.DeviceKey, DEVICE_KEY_PREFIX, wcslen(DEVICE_KEY_PREFIX)) != 0)
/* check that DeviceKey begins with DEVICE_KEY_PREFIX */
if (wcsncmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX, NS_ARRAY_LENGTH(DEVICE_KEY_PREFIX)-1) != 0)
return;
// make sure the string is NULL terminated
size_t i;
for (i = 0; i < sizeof(lpDisplayDevice.DeviceKey); i++) {
if (lpDisplayDevice.DeviceKey[i] == L'\0')
break;
}
if (i == sizeof(lpDisplayDevice.DeviceKey)) {
// we did not find a NULL
return;
if (wcsnlen(displayDevice.DeviceKey, NS_ARRAY_LENGTH(displayDevice.DeviceKey))
== NS_ARRAY_LENGTH(displayDevice.DeviceKey)) {
// we did not find a NULL
return;
}
// chop off DEVICE_KEY_PREFIX
mDeviceKey = lpDisplayDevice.DeviceKey + wcslen(DEVICE_KEY_PREFIX);
mDeviceKey = displayDevice.DeviceKey + NS_ARRAY_LENGTH(DEVICE_KEY_PREFIX)-1;
mDeviceID = lpDisplayDevice.DeviceID;
mDeviceString = lpDisplayDevice.DeviceString;
mDeviceID = displayDevice.DeviceID;
mDeviceString = displayDevice.DeviceString;
HKEY key, subkey;
LONG result, enumresult;
DWORD index = 0;
TCHAR subkeyname[64];
TCHAR value[128];
WCHAR subkeyname[64];
WCHAR value[128];
DWORD dwcbData = sizeof(subkeyname);
// "{4D36E968-E325-11CE-BFC1-08002BE10318}" is the display class

View File

@ -226,6 +226,8 @@
#include "nsICrashReporter.h"
#endif
#include "nsIXULRuntime.h"
using namespace mozilla::widget;
/**************************************************************
@ -2439,20 +2441,6 @@ void nsWindow::SetTransparencyMode(nsTransparencyMode aMode)
GetTopLevelWindow(PR_TRUE)->SetWindowTranslucencyInner(aMode);
}
namespace {
BOOL CALLBACK AddClientAreaToRegion(HWND hWnd, LPARAM lParam) {
nsIntRegion *region = reinterpret_cast<nsIntRegion*>(lParam);
RECT clientRect;
::GetWindowRect(hWnd, &clientRect);
nsIntRect clientArea(clientRect.left, clientRect.top,
clientRect.right - clientRect.left,
clientRect.bottom - clientRect.top);
region->Or(*region, clientArea);
return TRUE;
}
}
void nsWindow::UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion,
const nsIntRegion &aPossiblyTransparentRegion) {
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
@ -2468,24 +2456,10 @@ void nsWindow::UpdatePossiblyTransparentRegion(const nsIntRegion &aDirtyRegion,
mPossiblyTransparentRegion.Sub(mPossiblyTransparentRegion, aDirtyRegion);
mPossiblyTransparentRegion.Or(mPossiblyTransparentRegion, aPossiblyTransparentRegion);
nsIntRegion childWindowRegion;
::EnumChildWindows(mWnd, AddClientAreaToRegion, reinterpret_cast<LPARAM>(&childWindowRegion));
nsIntPoint clientOffset = GetClientOffset();
childWindowRegion.MoveBy(-clientOffset);
RECT r;
::GetWindowRect(mWnd, &r);
childWindowRegion.MoveBy(-r.left, -r.top);
nsIntRect clientBounds;
topWindow->GetClientBounds(clientBounds);
nsIntRegion opaqueRegion;
opaqueRegion.Sub(clientBounds, mPossiblyTransparentRegion);
opaqueRegion.Or(opaqueRegion, childWindowRegion);
// Sometimes child windows overlap our bounds
opaqueRegion.And(opaqueRegion, clientBounds);
MARGINS margins = { 0, 0, 0, 0 };
DWORD_PTR dwStyle = ::GetWindowLongPtrW(hWnd, GWL_STYLE);
@ -3217,34 +3191,45 @@ nsWindow::GetLayerManager()
#ifndef WINCE
if (!mLayerManager) {
if (mUseAcceleratedRendering) {
nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
PRBool allowAcceleration = PR_TRUE;
PRBool preferOpenGL = PR_FALSE;
if (prefs) {
prefs->GetBoolPref("mozilla.widget.accelerated-layers",
&allowAcceleration);
prefs->GetBoolPref("mozilla.layers.prefer-opengl",
&preferOpenGL);
}
if (allowAcceleration) {
PRBool accelerateByDefault = PR_TRUE;
PRBool disableAcceleration = PR_FALSE;
PRBool preferOpenGL = PR_FALSE;
if (prefs) {
prefs->GetBoolPref("layers.accelerate-all",
&accelerateByDefault);
prefs->GetBoolPref("layers.accelerate-none",
&disableAcceleration);
prefs->GetBoolPref("layers.prefer-opengl",
&preferOpenGL);
}
nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
PRBool safeMode = PR_FALSE;
if (xr)
xr->GetInSafeMode(&safeMode);
if (disableAcceleration || safeMode)
mUseAcceleratedRendering = PR_FALSE;
else if (accelerateByDefault)
mUseAcceleratedRendering = PR_TRUE;
if (mUseAcceleratedRendering) {
#ifdef MOZ_ENABLE_D3D9_LAYER
if (!preferOpenGL) {
nsRefPtr<mozilla::layers::LayerManagerD3D9> layerManager =
new mozilla::layers::LayerManagerD3D9(this);
if (layerManager->Initialize()) {
mLayerManager = layerManager;
}
if (!preferOpenGL) {
nsRefPtr<mozilla::layers::LayerManagerD3D9> layerManager =
new mozilla::layers::LayerManagerD3D9(this);
if (layerManager->Initialize()) {
mLayerManager = layerManager;
}
}
#endif
if (!mLayerManager) {
nsRefPtr<mozilla::layers::LayerManagerOGL> layerManager =
new mozilla::layers::LayerManagerOGL(this);
if (layerManager->Initialize()) {
mLayerManager = layerManager;
}
if (!mLayerManager) {
nsRefPtr<mozilla::layers::LayerManagerOGL> layerManager =
new mozilla::layers::LayerManagerOGL(this);
if (layerManager->Initialize()) {
mLayerManager = layerManager;
}
}
}
@ -6860,6 +6845,8 @@ nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
// We put the region back just below, anyway.
::SetWindowRgn(w->mWnd, NULL, TRUE);
#endif
nsresult rv = w->SetWindowClipRegion(configuration.mClipRegion, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
nsIntRect bounds;
w->GetBounds(bounds);
if (bounds.Size() != configuration.mBounds.Size()) {
@ -6869,7 +6856,7 @@ nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
} else if (bounds.TopLeft() != configuration.mBounds.TopLeft()) {
w->Move(configuration.mBounds.x, configuration.mBounds.y);
}
nsresult rv = w->SetWindowClipRegion(configuration.mClipRegion, PR_FALSE);
rv = w->SetWindowClipRegion(configuration.mClipRegion, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
@ -6904,6 +6891,14 @@ nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
if (!aIntersectWithExisting) {
if (!StoreWindowClipRegion(aRects))
return NS_OK;
} else {
// In this case still early return if nothing changed.
if (mClipRects && mClipRectCount == aRects.Length() &&
memcmp(mClipRects,
aRects.Elements(),
sizeof(nsIntRect)*mClipRectCount) == 0) {
return NS_OK;
}
}
HRGN dest = CreateHRGNFromArray(aRects);

View File

@ -51,6 +51,7 @@
#include "nsIPrefBranch2.h"
#include "BasicLayers.h"
#include "LayerManagerOGL.h"
#include "nsIXULRuntime.h"
#ifdef DEBUG
#include "nsIObserver.h"
@ -762,13 +763,27 @@ LayerManager* nsBaseWidget::GetLayerManager()
if (!mLayerManager) {
nsCOMPtr<nsIPrefBranch2> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
PRBool allowAcceleration = PR_TRUE;
PRBool disableAcceleration = PR_FALSE;
PRBool accelerateByDefault = PR_TRUE;
if (prefs) {
prefs->GetBoolPref("mozilla.widget.accelerated-layers",
&allowAcceleration);
prefs->GetBoolPref("layers.accelerate-all",
&accelerateByDefault);
prefs->GetBoolPref("layers.accelerate-none",
&disableAcceleration);
}
if (mUseAcceleratedRendering && allowAcceleration) {
nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
PRBool safeMode = PR_FALSE;
if (xr)
xr->GetInSafeMode(&safeMode);
if (disableAcceleration || safeMode)
mUseAcceleratedRendering = PR_FALSE;
else if (accelerateByDefault)
mUseAcceleratedRendering = PR_TRUE;
if (mUseAcceleratedRendering) {
nsRefPtr<LayerManagerOGL> layerManager =
new mozilla::layers::LayerManagerOGL(this);
/**