diff --git a/accessible/tests/browser/browser.ini b/accessible/tests/browser/browser.ini
index e9a5ab63a9d9..11c7318b8139 100644
--- a/accessible/tests/browser/browser.ini
+++ b/accessible/tests/browser/browser.ini
@@ -10,7 +10,7 @@ support-files =
[browser_shutdown_multi_acc_reference_doc.js]
[browser_shutdown_multi_reference.js]
[browser_shutdown_parent_own_reference.js]
-skip-if = !e10s # e10s specific test for a11y start/shutdown between parent and content.
+skip-if = !e10s || (os == 'win' && os_version == '5.1') # e10s specific test for a11y start/shutdown between parent and content.
[browser_shutdown_proxy_acc_reference.js]
skip-if = !e10s || (os == 'win') # e10s specific test for a11y start/shutdown between parent and content.
[browser_shutdown_proxy_doc_acc_reference.js]
@@ -20,10 +20,10 @@ skip-if = !e10s || (os == 'win') # e10s specific test for a11y start/shutdown be
[browser_shutdown_multi_proxy_acc_reference_obj.js]
skip-if = !e10s || (os == 'win') # e10s specific test for a11y start/shutdown between parent and content.
[browser_shutdown_remote_no_reference.js]
-skip-if = !e10s # e10s specific test for a11y start/shutdown between parent and content.
+skip-if = !e10s || (os == 'win' && os_version == '5.1') # e10s specific test for a11y start/shutdown between parent and content.
[browser_shutdown_remote_only.js]
-skip-if = !e10s # e10s specific test for a11y start/shutdown between parent and content.
+skip-if = !e10s || (os == 'win' && os_version == '5.1') # e10s specific test for a11y start/shutdown between parent and content.
[browser_shutdown_remote_own_reference.js]
-skip-if = !e10s # e10s specific test for a11y start/shutdown between parent and content.
+skip-if = !e10s || (os == 'win' && os_version == '5.1') # e10s specific test for a11y start/shutdown between parent and content.
[browser_shutdown_scope_lifecycle.js]
[browser_shutdown_start_restart.js]
diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini
index 58c55ee6f955..91df6353bb29 100644
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -272,7 +272,6 @@ tags = mcb
[browser_bug970746.js]
[browser_bug1015721.js]
skip-if = os == 'win'
-[browser_bug1064280_changeUrlInPinnedTab.js]
[browser_accesskeys.js]
[browser_clipboard.js]
subsuite = clipboard
diff --git a/browser/base/content/test/newtab/browser.ini b/browser/base/content/test/newtab/browser.ini
index 3931f35b602e..2ff40d72d9e1 100644
--- a/browser/base/content/test/newtab/browser.ini
+++ b/browser/base/content/test/newtab/browser.ini
@@ -8,6 +8,7 @@ support-files =
[browser_newtab_block.js]
[browser_newtab_bug721442.js]
[browser_newtab_bug722273.js]
+skip-if = (os == "mac" && debug) # temporary skip-if due to increase in intermittent failures on Mac debug - bug 1119906
[browser_newtab_bug723102.js]
[browser_newtab_bug723121.js]
[browser_newtab_bug725996.js]
diff --git a/browser/base/content/test/tabs/browser.ini b/browser/base/content/test/tabs/browser.ini
index 7771e0a6efb3..a8f714dfd6bf 100644
--- a/browser/base/content/test/tabs/browser.ini
+++ b/browser/base/content/test/tabs/browser.ini
@@ -2,3 +2,4 @@
skip-if = !e10s # Tab spinner is e10s only.
[browser_tabSwitchPrintPreview.js]
skip-if = os == 'mac'
+[browser_navigatePinnedTab.js]
diff --git a/browser/base/content/test/general/browser_bug1064280_changeUrlInPinnedTab.js b/browser/base/content/test/tabs/browser_navigatePinnedTab.js
similarity index 51%
rename from browser/base/content/test/general/browser_bug1064280_changeUrlInPinnedTab.js
rename to browser/base/content/test/tabs/browser_navigatePinnedTab.js
index 89e41df0e75c..e92e3edf5877 100644
--- a/browser/base/content/test/general/browser_bug1064280_changeUrlInPinnedTab.js
+++ b/browser/base/content/test/tabs/browser_navigatePinnedTab.js
@@ -29,8 +29,31 @@ add_task(function* () {
is(appTab.linkedBrowser.currentURI.spec, TEST_LINK_CHANGED,
"New page loaded in the app tab");
is(gBrowser.tabs.length, initialTabsNo, "No additional tabs were opened");
+
+ // Now check that opening a link that does create a new tab works,
+ // and also that it nulls out the opener.
+ let pageLoadPromise = BrowserTestUtils.browserLoaded(appTab.linkedBrowser, "http://example.com/");
+ yield BrowserTestUtils.loadURI(appTab.linkedBrowser, "http://example.com/");
+ info("Started loading example.com");
+ yield pageLoadPromise;
+ info("Loaded example.com");
+ let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, "http://example.org/");
+ yield ContentTask.spawn(browser, null, function* () {
+ let link = content.document.createElement("a");
+ link.href = "http://example.org/";
+ content.document.body.appendChild(link);
+ link.click();
+ });
+ info("Created & clicked link");
+ let extraTab = yield newTabPromise;
+ info("Got a new tab");
+ yield ContentTask.spawn(extraTab.linkedBrowser, null, function* () {
+ is(content.opener, null, "No opener should be available");
+ });
+ yield BrowserTestUtils.removeTab(extraTab);
});
+
registerCleanupFunction(function() {
gBrowser.removeTab(gBrowser.selectedTab);
});
diff --git a/browser/branding/aurora/branding.nsi b/browser/branding/aurora/branding.nsi
index bb42794d145c..2341b7433a1d 100644
--- a/browser/branding/aurora/branding.nsi
+++ b/browser/branding/aurora/branding.nsi
@@ -14,7 +14,8 @@
!define URLInfoAbout "https://www.mozilla.org"
!define HelpLink "https://support.mozilla.org"
-!define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-aurora-latest"
+!define URLStubDownload32 "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-aurora-latest"
+!define URLStubDownload64 "http://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-aurora-latest"
!define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=aurora&installer_lang=${AB_CD}"
!define URLSystemRequirements "https://www.mozilla.org/firefox/system-requirements/"
!define Channel "aurora"
diff --git a/browser/branding/nightly/branding.nsi b/browser/branding/nightly/branding.nsi
index fa13b32c6d6e..ba6b4e514735 100644
--- a/browser/branding/nightly/branding.nsi
+++ b/browser/branding/nightly/branding.nsi
@@ -13,7 +13,8 @@
!define URLInfoAbout "https://www.mozilla.org"
!define HelpLink "https://support.mozilla.org"
-!define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-nightly-latest"
+!define URLStubDownload32 "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-nightly-latest"
+!define URLStubDownload64 "http://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-nightly-latest"
!define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=nightly&installer_lang=${AB_CD}"
!define URLSystemRequirements "https://www.mozilla.org/firefox/system-requirements/"
!define Channel "nightly"
diff --git a/browser/branding/official/branding.nsi b/browser/branding/official/branding.nsi
index 5960f3107ad2..a6025a326d5c 100644
--- a/browser/branding/official/branding.nsi
+++ b/browser/branding/official/branding.nsi
@@ -18,7 +18,8 @@
; Beta since they share the same branding when building with other branches that
; set the update channel to beta.
!define OFFICIAL
-!define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownload32 "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownload64 "http://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-latest"
!define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=release&installer_lang=${AB_CD}"
!define URLSystemRequirements "https://www.mozilla.org/firefox/system-requirements/"
!define Channel "release"
diff --git a/browser/branding/unofficial/branding.nsi b/browser/branding/unofficial/branding.nsi
index 34214453f9da..8a81823311fe 100644
--- a/browser/branding/unofficial/branding.nsi
+++ b/browser/branding/unofficial/branding.nsi
@@ -13,7 +13,8 @@
!define URLInfoAbout "https://www.mozilla.org"
!define HelpLink "https://support.mozilla.org"
-!define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownload32 "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-latest"
+!define URLStubDownload64 "http://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-latest"
!define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=release&installer_lang=${AB_CD}"
!define URLSystemRequirements "https://www.mozilla.org/firefox/system-requirements/"
!define Channel "unofficial"
diff --git a/browser/components/contextualidentity/test/browser/browser_count_and_remove.js b/browser/components/contextualidentity/test/browser/browser_count_and_remove.js
index 23b7e948a23e..ee6043f137ad 100644
--- a/browser/components/contextualidentity/test/browser/browser_count_and_remove.js
+++ b/browser/components/contextualidentity/test/browser/browser_count_and_remove.js
@@ -22,13 +22,26 @@ add_task(function* test() {
openTabInUserContext(1);
is(ContextualIdentityService.countContainerTabs(), 1, "1 container tab created");
+ is(ContextualIdentityService.countContainerTabs(1), 1, "1 container tab created with id 1");
+ is(ContextualIdentityService.countContainerTabs(2), 0, "0 container tabs created with id 2");
openTabInUserContext(1);
- is(ContextualIdentityService.countContainerTabs(), 2, "2 container tab created");
+ is(ContextualIdentityService.countContainerTabs(), 2, "2 container tabs created");
+ is(ContextualIdentityService.countContainerTabs(1), 2, "2 container tabs created with id 1");
+ is(ContextualIdentityService.countContainerTabs(2), 0, "0 container tabs created with id 2");
openTabInUserContext(2);
is(ContextualIdentityService.countContainerTabs(), 3, "3 container tab created");
+ is(ContextualIdentityService.countContainerTabs(1), 2, "2 container tabs created with id 1");
+ is(ContextualIdentityService.countContainerTabs(2), 1, "1 container tab created with id 2");
- ContextualIdentityService.closeAllContainerTabs();
- is(ContextualIdentityService.countContainerTabs(), 0, "0 container tab at the end.");
+ ContextualIdentityService.closeContainerTabs(1);
+ is(ContextualIdentityService.countContainerTabs(), 1, "1 container tab created");
+ is(ContextualIdentityService.countContainerTabs(1), 0, "0 container tabs created with id 1");
+ is(ContextualIdentityService.countContainerTabs(2), 1, "1 container tab created with id 2");
+
+ ContextualIdentityService.closeContainerTabs();
+ is(ContextualIdentityService.countContainerTabs(), 0, "0 container tabs at the end.");
+ is(ContextualIdentityService.countContainerTabs(1), 0, "0 container tabs at the end with id 1.");
+ is(ContextualIdentityService.countContainerTabs(2), 0, "0 container tabs at the end with id 2.");
});
diff --git a/browser/components/preferences/in-content/containers.js b/browser/components/preferences/in-content/containers.js
index f63806a3d6dd..7968f55395a4 100644
--- a/browser/components/preferences/in-content/containers.js
+++ b/browser/components/preferences/in-content/containers.js
@@ -39,10 +39,34 @@ let gContainersPane = {
},
onRemoveClick(button) {
- let userContextId = button.getAttribute("value");
+ let userContextId = parseInt(button.getAttribute("value"), 10);
+
+ let count = ContextualIdentityService.countContainerTabs(userContextId);
+ if (count > 0) {
+ let bundlePreferences = document.getElementById("bundlePreferences");
+
+ let title = bundlePreferences.getString("removeContainerAlertTitle");
+ let message = PluralForm.get(count, bundlePreferences.getString("removeContainerMsg"))
+ .replace("#S", count)
+ let okButton = bundlePreferences.getString("removeContainerOkButton");
+ let cancelButton = bundlePreferences.getString("removeContainerButton2");
+
+ let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
+ (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
+
+ let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
+ okButton, cancelButton, null, null, {});
+ if (rv != 0) {
+ return;
+ }
+
+ ContextualIdentityService.closeContainerTabs(userContextId);
+ }
+
ContextualIdentityService.remove(userContextId);
this._rebuildView();
},
+
onPeferenceClick(button) {
this.openPreferenceDialog(button.getAttribute("value"));
},
diff --git a/browser/components/preferences/in-content/privacy.js b/browser/components/preferences/in-content/privacy.js
index ffa7a9c391d5..d71e77e99c66 100644
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -104,7 +104,7 @@ var gPrivacyPane = {
let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
okButton, cancelButton, null, null, {});
if (rv == 0) {
- ContextualIdentityService.closeAllContainerTabs();
+ ContextualIdentityService.closeContainerTabs();
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
return;
}
diff --git a/browser/installer/windows/nsis/stub.nsi b/browser/installer/windows/nsis/stub.nsi
index 72ac7ee010ad..d641592bfb01 100644
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -35,11 +35,10 @@ Var LabelDownloading
Var LabelInstalling
Var LabelFreeSpace
Var CheckboxSetAsDefault
-Var CheckboxShortcutOnBar ; Used for Quicklaunch or Taskbar as appropriate
-Var CheckboxShortcutInStartMenu
-Var CheckboxShortcutOnDesktop
+Var CheckboxShortcuts
Var CheckboxSendPing
Var CheckboxInstallMaintSvc
+Var DroplistArch
Var DirRequest
Var ButtonBrowse
Var LabelBlurb1
@@ -73,7 +72,6 @@ Var InstallStepSize
Var InstallTotalSteps
Var ProgressCompleted
Var ProgressTotal
-Var TmpVal
Var ExitCode
Var FirefoxLaunchCode
@@ -108,6 +106,8 @@ Var DownloadRetryCount
Var OpenedDownloadPage
Var DownloadServerIP
Var PostSigningData
+Var PreviousInstallDir
+Var PreviousInstallArch
Var ControlHeightPX
Var ControlRightPX
@@ -218,6 +218,9 @@ Var ControlRightPX
!define INVALID_HANDLE_VALUE -1
!endif
+!define DefaultInstDir32bit "$PROGRAMFILES32\${BrandFullName}"
+!define DefaultInstDir64bit "$PROGRAMFILES64\${BrandFullName}"
+
!include "nsDialogs.nsh"
!include "LogicLib.nsh"
!include "FileFunc.nsh"
@@ -230,6 +233,9 @@ Var ControlRightPX
!insertmacro LineFind
!insertmacro StrFilter
+!include "StrFunc.nsh"
+${StrTok}
+
!include "locales.nsi"
!include "branding.nsi"
@@ -243,8 +249,10 @@ Var ControlRightPX
; set the update channel to beta.
!ifdef OFFICIAL
!ifdef BETA_UPDATE_CHANNEL
-!undef URLStubDownload
-!define URLStubDownload "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-beta-latest"
+!undef URLStubDownload32
+!undef URLStubDownload64
+!define URLStubDownload32 "http://download.mozilla.org/?os=win&lang=${AB_CD}&product=firefox-beta-latest"
+!define URLStubDownload64 "http://download.mozilla.org/?os=win64&lang=${AB_CD}&product=firefox-beta-latest"
!undef URLManualDownload
!define URLManualDownload "https://www.mozilla.org/${AB_CD}/firefox/installer-help/?channel=beta&installer_lang=${AB_CD}"
!undef Channel
@@ -275,11 +283,6 @@ icon "setup.ico"
XPStyle on
BrandingText " "
ChangeUI all "nsisui.exe"
-!ifdef HAVE_64BIT_BUILD
- InstallDir "$PROGRAMFILES64\${BrandFullName}\"
-!else
- InstallDir "$PROGRAMFILES32\${BrandFullName}\"
-!endif
!ifdef ${AB_CD}_rtl
LoadLanguageFile "locale-rtl.nlf"
@@ -340,9 +343,11 @@ Function .onInit
Quit
${EndIf}
-!ifdef HAVE_64BIT_BUILD
- SetRegView 64
-!endif
+ ${If} ${RunningX64}
+ StrCpy $INSTDIR "${DefaultInstDir64bit}"
+ ${Else}
+ StrCpy $INSTDIR "${DefaultInstDir32bit}"
+ ${EndIf}
; Require elevation if the user can elevate
${ElevateUAC}
@@ -355,16 +360,25 @@ Function .onInit
${EndIf}
!endif
+ ; If we have any existing installation, use its location as the default
+ ; path for this install, even if it's not the same architecture.
+ SetRegView 32
SetShellVarContext all ; Set SHCTX to HKLM
${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
+ ${If} "$R9" == "false"
+ ${AndIf} ${RunningX64}
+ SetRegView 64
+ ${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
+ ${EndIf}
+
${If} "$R9" == "false"
SetShellVarContext current ; Set SHCTX to HKCU
${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
${If} ${RunningX64}
; In HKCU there is no WOW64 redirection, which means we may have gotten
- ; the path to a 32-bit install even though we're 64-bit, or vice-versa.
+ ; the path to a 32-bit install even though we're 64-bit.
; In that case, just use the default path instead of offering an upgrade.
; But only do that override if the existing install is in Program Files,
; because that's the only place we can be sure is specific
@@ -372,20 +386,36 @@ Function .onInit
; The WordFind syntax below searches for the first occurence of the
; "delimiter" (the Program Files path) in the install path and returns
; anything that appears before that. If nothing appears before that,
- ; then the install is under Program Files (32 or 64).
-!ifdef HAVE_64BIT_BUILD
+ ; then the install is under Program Files.
${WordFind} $R9 $PROGRAMFILES32 "+1{" $0
-!else
- ${WordFind} $R9 $PROGRAMFILES64 "+1{" $0
-!endif
${If} $0 == ""
StrCpy $R9 "false"
${EndIf}
${EndIf}
${EndIf}
+ StrCpy $PreviousInstallDir ""
+ StrCpy $PreviousInstallArch ""
${If} "$R9" != "false"
- StrCpy $INSTDIR "$R9"
+ ; Don't override the default install path with an existing installation
+ ; of a different architecture.
+ System::Call "*(i)p.r0"
+ StrCpy $1 "$R9\${FileMainEXE}"
+ System::Call "Kernel32::GetBinaryTypeW(w r1, p r0)i"
+ System::Call "*$0(i.r2)"
+ System::Free $0
+
+ ${If} $2 == "6" ; 6 == SCS_64BIT_BINARY
+ ${AndIf} ${RunningX64}
+ StrCpy $PreviousInstallDir "$R9"
+ StrCpy $PreviousInstallArch "64"
+ StrCpy $INSTDIR "$PreviousInstallDir"
+ ${ElseIf} $2 == "0" ; 0 == SCS_32BIT_BINARY
+ ${AndIfNot} ${RunningX64}
+ StrCpy $PreviousInstallDir "$R9"
+ StrCpy $PreviousInstallArch "32"
+ StrCpy $INSTDIR "$PreviousInstallDir"
+ ${EndIf}
${EndIf}
; Used to determine if the default installation directory was used.
@@ -422,9 +452,7 @@ Function .onInit
StrCpy $InitialInstallRequirementsCode ""
StrCpy $IsDownloadFinished ""
StrCpy $FirefoxLaunchCode "0"
- StrCpy $CheckboxShortcutOnBar "1"
- StrCpy $CheckboxShortcutInStartMenu "1"
- StrCpy $CheckboxShortcutOnDesktop "1"
+ StrCpy $CheckboxShortcuts "1"
StrCpy $CheckboxSendPing "1"
!ifdef MOZ_MAINTENANCE_SERVICE
StrCpy $CheckboxInstallMaintSvc "1"
@@ -432,6 +460,11 @@ Function .onInit
StrCpy $CheckboxInstallMaintSvc "0"
!endif
StrCpy $WasOptionsButtonClicked "0"
+ ${If} ${RunningX64}
+ StrCpy $DroplistArch "$(VERSION_64BIT)"
+ ${Else}
+ StrCpy $DroplistArch "$(VERSION_32BIT)"
+ ${EndIf}
StrCpy $0 ""
!ifdef FONT_FILE1
@@ -575,11 +608,11 @@ Function SendPing
; completion of all phases.
${GetSecondsElapsed} "$EndInstallPhaseTickCount" "$EndFinishPhaseTickCount" $4
-!ifdef HAVE_64BIT_BUILD
- StrCpy $R0 "1"
-!else
- StrCpy $R0 "0"
-!endif
+ ${If} $DroplistArch == "$(VERSION_64BIT)"
+ StrCpy $R0 "1"
+ ${Else}
+ StrCpy $R0 "0"
+ ${EndIf}
${If} ${RunningX64}
StrCpy $R1 "1"
@@ -903,54 +936,13 @@ Function createOptions
; background colors of the Dialog must also be hardcoded.
SetCtlColors $Dialog ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
- ${NSD_CreateLabel} ${OPTIONS_ITEM_EDGE_DU} 18u ${OPTIONS_ITEM_WIDTH_DU} \
- 12u "$(CREATE_SHORTCUTS)"
- Pop $0
- SetCtlColors $0 ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
- SendMessage $0 ${WM_SETFONT} $FontNormal 0
-
- ${If} ${AtLeastWin7}
- StrCpy $0 "$(ADD_SC_TASKBAR)"
- ${Else}
- StrCpy $0 "$(ADD_SC_QUICKLAUNCHBAR)"
- ${EndIf}
- ${NSD_CreateCheckbox} ${OPTIONS_SUBITEM_EDGE_DU} 38u \
- ${OPTIONS_SUBITEM_WIDTH_DU} 12u "$0"
- Pop $CheckboxShortcutOnBar
- ; The uxtheme must be disabled on checkboxes in order to override the system
- ; font color.
- System::Call 'uxtheme::SetWindowTheme(i $CheckboxShortcutOnBar, w " ", w " ")'
- SetCtlColors $CheckboxShortcutOnBar ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
- SendMessage $CheckboxShortcutOnBar ${WM_SETFONT} $FontNormal 0
- ${NSD_Check} $CheckboxShortcutOnBar
-
- ${NSD_CreateCheckbox} ${OPTIONS_SUBITEM_EDGE_DU} 54u ${OPTIONS_SUBITEM_WIDTH_DU} \
- 12u "$(ADD_CheckboxShortcutInStartMenu)"
- Pop $CheckboxShortcutInStartMenu
- ; The uxtheme must be disabled on checkboxes in order to override the system
- ; font color.
- System::Call 'uxtheme::SetWindowTheme(i $CheckboxShortcutInStartMenu, w " ", w " ")'
- SetCtlColors $CheckboxShortcutInStartMenu ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
- SendMessage $CheckboxShortcutInStartMenu ${WM_SETFONT} $FontNormal 0
- ${NSD_Check} $CheckboxShortcutInStartMenu
-
- ${NSD_CreateCheckbox} ${OPTIONS_SUBITEM_EDGE_DU} 70u ${OPTIONS_SUBITEM_WIDTH_DU} \
- 12u "$(ADD_CheckboxShortcutOnDesktop)"
- Pop $CheckboxShortcutOnDesktop
- ; The uxtheme must be disabled on checkboxes in order to override the system
- ; font color.
- System::Call 'uxtheme::SetWindowTheme(i $CheckboxShortcutOnDesktop, w " ", w " ")'
- SetCtlColors $CheckboxShortcutOnDesktop ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
- SendMessage $CheckboxShortcutOnDesktop ${WM_SETFONT} $FontNormal 0
- ${NSD_Check} $CheckboxShortcutOnDesktop
-
- ${NSD_CreateLabel} ${OPTIONS_ITEM_EDGE_DU} 100u ${OPTIONS_ITEM_WIDTH_DU} \
+ ${NSD_CreateLabel} ${OPTIONS_ITEM_EDGE_DU} 25u ${OPTIONS_ITEM_WIDTH_DU} \
12u "$(DEST_FOLDER)"
Pop $0
SetCtlColors $0 ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
SendMessage $0 ${WM_SETFONT} $FontNormal 0
- ${NSD_CreateDirRequest} ${OPTIONS_SUBITEM_EDGE_DU} 116u 159u 14u "$INSTDIR"
+ ${NSD_CreateDirRequest} ${OPTIONS_SUBITEM_EDGE_DU} 41u 159u 14u "$INSTDIR"
Pop $DirRequest
SetCtlColors $DirRequest ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
SendMessage $DirRequest ${WM_SETFONT} $FontNormal 0
@@ -966,7 +958,7 @@ Function createOptions
${NSD_AddExStyle} $DirRequest ${WS_EX_LTRREADING}|${WS_EX_LEFT}
!endif
- ${NSD_CreateBrowseButton} 280u 116u 50u 14u "$(BROWSE_BUTTON)"
+ ${NSD_CreateBrowseButton} 280u 41u 50u 14u "$(BROWSE_BUTTON)"
Pop $ButtonBrowse
SetCtlColors $ButtonBrowse "" ${COMMON_BKGRD_COLOR}
${NSD_OnClick} $ButtonBrowse OnClick_ButtonBrowse
@@ -987,13 +979,13 @@ Function createOptions
IntOp $0 $0 + 8 ; Add padding to the control's width
; Make both controls the same width as the widest control
- ${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 134u $0 $ControlHeightPX "$(SPACE_REQUIRED)"
+ ${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 59u $0 $ControlHeightPX "$(SPACE_REQUIRED)"
Pop $5
SetCtlColors $5 ${COMMON_TEXT_COLOR_FADED} ${COMMON_BKGRD_COLOR}
SendMessage $5 ${WM_SETFONT} $FontItalic 0
IntOp $2 $2 + 8 ; Add padding to the control's width
- ${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 145u $2 $ControlHeightPX "$(SPACE_AVAILABLE)"
+ ${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 70u $2 $ControlHeightPX "$(SPACE_AVAILABLE)"
Pop $6
SetCtlColors $6 ${COMMON_TEXT_COLOR_FADED} ${COMMON_BKGRD_COLOR}
SendMessage $6 ${WM_SETFONT} $FontItalic 0
@@ -1007,7 +999,7 @@ Function createOptions
IntOp $ControlRightPX $ControlRightPX + 6
- ${NSD_CreateLabel} $ControlRightPX 134u 100% $ControlHeightPX \
+ ${NSD_CreateLabel} $ControlRightPX 59u 100% $ControlHeightPX \
"${APPROXIMATE_REQUIRED_SPACE_MB} $(MEGA)$(BYTE)"
Pop $7
SetCtlColors $7 ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
@@ -1015,14 +1007,29 @@ Function createOptions
; Create the free space label with an empty string and update it by calling
; UpdateFreeSpaceLabel
- ${NSD_CreateLabel} $ControlRightPX 145u 100% $ControlHeightPX " "
+ ${NSD_CreateLabel} $ControlRightPX 70u 100% $ControlHeightPX " "
Pop $LabelFreeSpace
SetCtlColors $LabelFreeSpace ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
SendMessage $LabelFreeSpace ${WM_SETFONT} $FontNormal 0
Call UpdateFreeSpaceLabel
- ${NSD_CreateCheckbox} ${OPTIONS_ITEM_EDGE_DU} 168u ${OPTIONS_SUBITEM_WIDTH_DU} \
+ ${If} ${AtLeastWin7}
+ StrCpy $0 "$(ADD_SC_DESKTOP_TASKBAR)"
+ ${Else}
+ StrCpy $0 "$(ADD_SC_DESKTOP_QUICKLAUNCHBAR)"
+ ${EndIf}
+ ${NSD_CreateCheckbox} ${OPTIONS_ITEM_EDGE_DU} 100u \
+ ${OPTIONS_ITEM_WIDTH_DU} 12u "$0"
+ Pop $CheckboxShortcuts
+ ; The uxtheme must be disabled on checkboxes in order to override the system
+ ; font color.
+ System::Call 'uxtheme::SetWindowTheme(i $CheckboxShortcuts, w " ", w " ")'
+ SetCtlColors $CheckboxShortcuts ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
+ SendMessage $CheckboxShortcuts ${WM_SETFONT} $FontNormal 0
+ ${NSD_Check} $CheckboxShortcuts
+
+ ${NSD_CreateCheckbox} ${OPTIONS_ITEM_EDGE_DU} 116u ${OPTIONS_SUBITEM_WIDTH_DU} \
12u "$(SEND_PING)"
Pop $CheckboxSendPing
; The uxtheme must be disabled on checkboxes in order to override the system
@@ -1033,6 +1040,7 @@ Function createOptions
${NSD_Check} $CheckboxSendPing
!ifdef MOZ_MAINTENANCE_SERVICE
+ StrCpy $CheckboxInstallMaintSvc "0"
; We can only install the maintenance service if the user is an admin.
Call IsUserAdmin
Pop $0
@@ -1045,31 +1053,100 @@ Function createOptions
StrCpy $0 "false"
${EndIf}
- ; Only show the maintenance service checkbox if we have write access to HKLM
- ClearErrors
- WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \
- "Write Test"
- ${If} ${Errors}
- ${OrIf} $0 != "true"
- StrCpy $CheckboxInstallMaintSvc "0"
- ${Else}
+ ${If} $0 == "true"
+ ; Only show the maintenance service checkbox if we have write access to HKLM
DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
- ; Read the registry instead of using ServicesHelper::IsInstalled so the
- ; plugin isn't included in the stub installer to lessen its size.
ClearErrors
- ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\services\MozillaMaintenance" "ImagePath"
- ${If} ${Errors}
- ${NSD_CreateCheckbox} ${OPTIONS_ITEM_EDGE_DU} 184u ${OPTIONS_ITEM_WIDTH_DU} \
- 12u "$(INSTALL_MAINT_SERVICE)"
- Pop $CheckboxInstallMaintSvc
- System::Call 'uxtheme::SetWindowTheme(i $CheckboxInstallMaintSvc, w " ", w " ")'
- SetCtlColors $CheckboxInstallMaintSvc ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
- SendMessage $CheckboxInstallMaintSvc ${WM_SETFONT} $FontNormal 0
- ${NSD_Check} $CheckboxInstallMaintSvc
+ WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \
+ "Write Test"
+ ${IfNot} ${Errors}
+ DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
+ ; Read the registry instead of using ServicesHelper::IsInstalled so the
+ ; plugin isn't included in the stub installer to lessen its size.
+ ClearErrors
+ ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\services\MozillaMaintenance" "ImagePath"
+ ${If} ${Errors}
+ ${NSD_CreateCheckbox} ${OPTIONS_ITEM_EDGE_DU} 132u ${OPTIONS_ITEM_WIDTH_DU} \
+ 12u "$(INSTALL_MAINT_SERVICE)"
+ Pop $CheckboxInstallMaintSvc
+ System::Call 'uxtheme::SetWindowTheme(i $CheckboxInstallMaintSvc, w " ", w " ")'
+ SetCtlColors $CheckboxInstallMaintSvc ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
+ SendMessage $CheckboxInstallMaintSvc ${WM_SETFONT} $FontNormal 0
+ ${NSD_Check} $CheckboxInstallMaintSvc
+ ${EndIf}
${EndIf}
${EndIf}
!endif
+ ${If} ${RunningX64}
+ ; Get the exact pixel width we're going to need for this label.
+ ; The label string has a keyboard accelerator, which is an '&' that's in
+ ; the string but is not rendered, and GetTextExtent doesn't account for
+ ; those, so remove them first. Also handle any escaped &'s ("&&").
+ StrCpy $R0 "$(ARCH_DROPLIST_LABEL)"
+ StrCpy $R1 ""
+ ${Do}
+ ${StrTok} $R2 $R0 "&" 0 0
+ StrCpy $R1 "$R1$R2"
+ StrLen $R3 $R2
+ IntOp $R3 $R3 + 1
+ StrCpy $R0 $R0 "" $R3
+ StrCpy $R4 $R0 1
+ ${If} $R4 == "&"
+ StrCpy $R1 "$R1&"
+ StrCpy $R0 $R0 "" 1
+ ${EndIf}
+ ${LoopUntil} $R0 == ""
+
+ ${GetTextExtent} $R1 $FontNormal $R0 $R1
+ ${If} $CheckboxInstallMaintSvc == "0"
+ ${NSD_CreateLabel} ${OPTIONS_ITEM_EDGE_DU} 134u $R0 $R1 "$(ARCH_DROPLIST_LABEL)"
+ ${Else}
+ ${NSD_CreateLabel} ${OPTIONS_ITEM_EDGE_DU} 154u $R0 $R1 "$(ARCH_DROPLIST_LABEL)"
+ ${EndIf}
+ Pop $0
+ SetCtlColors $0 ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
+ SendMessage $0 ${WM_SETFONT} $FontNormal 0
+
+ ; Set the dropdown list size to the same as the larger of the two options.
+ ${GetTextExtent} "$(VERSION_32BIT)" $FontNormal $R0 $R1
+ ${GetTextExtent} "$(VERSION_64BIT)" $FontNormal $R2 $R3
+ ${If} $R0 < $R2
+ StrCpy $R0 $R2
+ ${EndIf}
+ ${If} $R1 < $R3
+ StrCpy $R3 $R1
+ ${EndIf}
+ ; Add enough width for the dropdown button. How wide the button is depends
+ ; on he system display scaling setting, which we cannot easily determine,
+ ; so just use a value that works fine for a setting of 200% and adds a
+ ; little too much padding for settings below that.
+ IntOp $R0 $R0 + 56
+
+ ; Put the droplist right after the label, with some padding.
+ ${GetDlgItemEndPX} $0 $ControlRightPX
+ IntOp $ControlRightPX $ControlRightPX + 4
+ ${If} $CheckboxInstallMaintSvc == "0"
+ ${NSD_CreateDropList} $ControlRightPX 132u $R0 $R3 ""
+ ${Else}
+ ${NSD_CreateDropList} $ControlRightPX 152u $R0 $R3 ""
+ ${EndIf}
+ Pop $DroplistArch
+ ${NSD_CB_AddString} $DroplistArch "$(VERSION_32BIT)"
+ ${NSD_CB_AddString} $DroplistArch "$(VERSION_64BIT)"
+ ${NSD_OnChange} $DroplistArch OnChange_DroplistArch
+ ; The uxtheme must be disabled in order to override the system colors.
+ System::Call 'uxtheme::SetWindowTheme(i $DroplistArch, w " ", w " ")'
+ SetCtlColors $DroplistArch ${COMMON_TEXT_COLOR_NORMAL} ${COMMON_BKGRD_COLOR}
+ SendMessage $DroplistArch ${WM_SETFONT} $FontNormal 0
+
+ ${If} ${RunningX64}
+ ${NSD_CB_SelectString} $DroplistArch "$(VERSION_64BIT)"
+ ${Else}
+ ${NSD_CB_SelectString} $DroplistArch "$(VERSION_32BIT)"
+ ${EndIf}
+ ${EndIf}
+
GetDlgItem $0 $HWNDPARENT 1 ; Install button
${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(UPGRADE_BUTTON)"
@@ -1137,9 +1214,8 @@ Function leaveOptions
IntOp $OptionsPhaseSeconds $OptionsPhaseSeconds + 1
${EndIf}
- ${NSD_GetState} $CheckboxShortcutOnBar $CheckboxShortcutOnBar
- ${NSD_GetState} $CheckboxShortcutInStartMenu $CheckboxShortcutInStartMenu
- ${NSD_GetState} $CheckboxShortcutOnDesktop $CheckboxShortcutOnDesktop
+ ${NSD_GetState} $CheckboxShortcuts $CheckboxShortcuts
+ ${NSD_GetText} $DroplistArch $DroplistArch
${NSD_GetState} $CheckboxSendPing $CheckboxSendPing
!ifdef MOZ_MAINTENANCE_SERVICE
${NSD_GetState} $CheckboxInstallMaintSvc $CheckboxInstallMaintSvc
@@ -1334,8 +1410,15 @@ FunctionEnd
Function StartDownload
${NSD_KillTimer} StartDownload
- InetBgDL::Get "${URLStubDownload}${URLStubDownloadAppend}" "$PLUGINSDIR\download.exe" \
- /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
+ ${If} $DroplistArch == "$(VERSION_64BIT)"
+ InetBgDL::Get "${URLStubDownload64}${URLStubDownloadAppend}" \
+ "$PLUGINSDIR\download.exe" \
+ /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
+ ${Else}
+ InetBgDL::Get "${URLStubDownload32}${URLStubDownloadAppend}" \
+ "$PLUGINSDIR\download.exe" \
+ /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
+ ${EndIf}
StrCpy $4 ""
${NSD_CreateTimer} OnDownload ${DownloadIntervalMS}
${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}"
@@ -1556,23 +1639,18 @@ Function OnDownload
; Don't create the QuickLaunch or Taskbar shortcut from the launched installer
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "QuickLaunchShortcut" "false"
- ; Either avoid or force adding a taskbar pin based on the checkbox value:
- ${If} $CheckboxShortcutOnBar == 0
+ ; Always create a start menu shortcut, so the user always has some way
+ ; to access the application.
+ WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "StartMenuShortcuts" "true"
+
+ ; Either avoid or force adding a taskbar pin and desktop shortcut
+ ; based on the checkbox value.
+ ${If} $CheckboxShortcuts == 0
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "TaskbarShortcut" "false"
+ WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "DesktopShortcut" "false"
${Else}
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "TaskbarShortcut" "true"
- ${EndIf}
-
- ${If} $CheckboxShortcutOnDesktop == 1
WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "DesktopShortcut" "true"
- ${Else}
- WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "DesktopShortcut" "false"
- ${EndIf}
-
- ${If} $CheckboxShortcutInStartMenu == 1
- WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "StartMenuShortcuts" "true"
- ${Else}
- WriteINIStr "$PLUGINSDIR\${CONFIG_INI}" "Install" "StartMenuShortcuts" "false"
${EndIf}
!ifdef MOZ_MAINTENANCE_SERVICE
@@ -1749,7 +1827,7 @@ Function FinishInstall
${EndIf}
${EndIf}
- ${If} $CheckboxShortcutOnBar == 1
+ ${If} $CheckboxShortcuts == 1
${If} ${AtMostWinVista}
ClearErrors
${GetParameters} $0
@@ -1885,6 +1963,30 @@ Function OnClick_ButtonBrowse
${EndIf}
FunctionEnd
+Function OnChange_DroplistArch
+ ; When the user changes the 32/64-bit setting, change the default install path
+ ; to use the correct version of Program Files. But only do that if the user
+ ; hasn't selected their own install path yet, and if we didn't select our
+ ; default as the location of an existing install.
+ ${If} $INSTDIR == $InitialInstallDir
+ ${NSD_GetText} $DroplistArch $0
+ ${If} $0 == "$(VERSION_32BIT)"
+ ${If} $PreviousInstallArch == 32
+ StrCpy $InitialInstallDir $PreviousInstallDir
+ ${Else}
+ StrCpy $InitialInstallDir "${DefaultInstDir32bit}"
+ ${EndIf}
+ ${Else}
+ ${If} $PreviousInstallArch == 64
+ StrCpy $InitialInstallDir $PreviousInstallDir
+ ${Else}
+ StrCpy $InitialInstallDir "${DefaultInstDir64bit}"
+ ${EndIf}
+ ${EndIf}
+ ${NSD_SetText} $DirRequest $InitialInstallDir
+ ${EndIf}
+FunctionEnd
+
Function CheckSpace
${If} "$ExistingTopDir" != ""
StrLen $0 "$ExistingTopDir"
@@ -1949,6 +2051,7 @@ Function CanWrite
GetTempFileName $2 "$0"
Delete $2
CreateDirectory "$2"
+
${If} ${FileExists} "$2"
${If} ${FileExists} "$INSTDIR"
GetTempFileName $3 "$INSTDIR"
diff --git a/browser/locales/en-US/chrome/browser/preferences/preferences.properties b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
index 149a952671eb..59ab19ba0f97 100644
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -198,3 +198,13 @@ disableContainersMsg=If you disable Container Tabs now, #S container tab will be
disableContainersOkButton=Close #S Container Tab;Close #S Container Tabs
disableContainersButton2=Keep enabled
+
+removeContainerAlertTitle=Remove This Container?
+
+# LOCALIZATION NOTE (removeContainerMsg): Semi-colon list of plural forms.
+# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
+# #S is the number of container tabs
+removeContainerMsg=If you remove this Container now, #S container tab will be closed. Are you sure you want to remove this Container?;If you remove this Container now, #S container tabs will be closed. Are you sure you want to remove this Container?
+
+removeContainerOkButton=Remove this Container
+removeContainerButton2=Don’t remove this Container
diff --git a/browser/locales/en-US/installer/nsisstrings.properties b/browser/locales/en-US/installer/nsisstrings.properties
index 389405696987..82c2c40bfec4 100644
--- a/browser/locales/en-US/installer/nsisstrings.properties
+++ b/browser/locales/en-US/installer/nsisstrings.properties
@@ -41,11 +41,11 @@ CANCEL_BUTTON=Cancel
OPTIONS_BUTTON=&Options
MAKE_DEFAULT=&Make $BrandShortName my default browser
-CREATE_SHORTCUTS=Create Shortcuts for $BrandShortName:
-ADD_SC_TASKBAR=On my &Task bar
-ADD_SC_QUICKLAUNCHBAR=On my &Quick Launch bar
-ADD_CheckboxShortcutInStartMenu=In my &Start Menu Programs Folder
-ADD_CheckboxShortcutOnDesktop=On my &Desktop
+ADD_SC_DESKTOP_TASKBAR=&Create desktop and taskbar shortcuts for $BrandShortName
+ADD_SC_DESKTOP_QUICKLAUNCHBAR=&Create desktop and quick launch shortcuts for $BrandShortName
+VERSION_32BIT=32-bit $BrandShortName
+VERSION_64BIT=64-bit $BrandShortName
+ARCH_DROPLIST_LABEL=&Version to install
SPACE_REQUIRED=Space Required:
SPACE_AVAILABLE=Space Available:
ONE_MOMENT_INSTALL=One moment, $BrandShortName will launch as soon as the install is complete…
diff --git a/browser/themes/shared/autocomplete.inc.css b/browser/themes/shared/autocomplete.inc.css
index f634bc9e4e4e..79402ff5c86f 100644
--- a/browser/themes/shared/autocomplete.inc.css
+++ b/browser/themes/shared/autocomplete.inc.css
@@ -12,15 +12,32 @@
padding: 0px 1px 0px 1px;
}
+#PopupAutoComplete > richlistbox > richlistitem > .ac-site-icon {
+ margin-inline-start: 4px;
+ margin-inline-end: 0;
+}
+
#PopupAutoComplete > richlistbox > richlistitem > .ac-title {
font: icon;
- margin-inline-start: 6px;
+ margin-inline-start: 4px;
}
#PopupAutoComplete > richlistbox {
padding: 0;
}
+
+/* Login form autocompletion */
+#PopupAutoComplete > richlistbox > richlistitem[originaltype="login"] > .ac-site-icon {
+ display: initial;
+ list-style-image: url(chrome://browser/skin/notification-icons.svg#login);
+}
+
+#PopupAutoComplete > richlistbox > richlistitem[originaltype="login"] > .ac-site-icon[selected] {
+ list-style-image: url(chrome://browser/skin/notification-icons.svg#login-highlighted);
+}
+
+
/* Insecure field warning */
#PopupAutoComplete > richlistbox > richlistitem[originaltype="insecureWarning"] {
background-color: #F6F6F6; /* Bug 1319176 */
diff --git a/browser/themes/shared/notification-icons.svg b/browser/themes/shared/notification-icons.svg
index 09b97533bee9..04ed3b950a74 100644
--- a/browser/themes/shared/notification-icons.svg
+++ b/browser/themes/shared/notification-icons.svg
@@ -21,6 +21,11 @@
clip-path: url(#clip);
}
+ #login-highlighted {
+ fill: HighlightText;
+ fill-opacity: 1;
+ }
+
#plugin-blocked,
#plugin-blocked:target ~ #strikeout {
fill: #d92215;
@@ -73,6 +78,7 @@
+
diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css
index 601dd2737a37..16fde196b8cf 100644
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -1106,7 +1106,11 @@ toolbar[brighttext] #close-button {
#minimize-button,
#restore-button,
#close-button {
- list-style-image: url("chrome://global/skin/icons/windowControls.png");
+ /* Important to ensure this applies even on toolbar[brighttext] */
+ list-style-image: url("chrome://global/skin/icons/windowControls.png") !important;
+ /* Also override background color to a avoid hover background styling
+ * leaking through around the image. */
+ background-color: transparent !important;
padding: 0;
}
diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp
index 5bd140814ce0..da85641d04c8 100644
--- a/build/clang-plugin/clang-plugin.cpp
+++ b/build/clang-plugin/clang-plugin.cpp
@@ -412,8 +412,8 @@ bool typeIsRefPtr(QualType Q) {
// The method defined in clang for ignoring implicit nodes doesn't work with
// some AST trees. To get around this, we define our own implementation of
-// IgnoreImplicit.
-const Stmt *IgnoreImplicit(const Stmt *s) {
+// IgnoreTrivials.
+const Stmt *IgnoreTrivials(const Stmt *s) {
while (true) {
if (auto *ewc = dyn_cast(s)) {
s = ewc->getSubExpr();
@@ -423,6 +423,8 @@ const Stmt *IgnoreImplicit(const Stmt *s) {
s = bte->getSubExpr();
} else if (auto *ice = dyn_cast(s)) {
s = ice->getSubExpr();
+ } else if (auto *pe = dyn_cast(s)) {
+ s = pe->getSubExpr();
} else {
break;
}
@@ -431,8 +433,8 @@ const Stmt *IgnoreImplicit(const Stmt *s) {
return s;
}
-const Expr *IgnoreImplicit(const Expr *e) {
- return cast(IgnoreImplicit(static_cast(e)));
+const Expr *IgnoreTrivials(const Expr *e) {
+ return cast(IgnoreTrivials(static_cast(e)));
}
}
@@ -905,6 +907,8 @@ AST_MATCHER(CXXRecordDecl, needsMemMovableMembers) {
AST_MATCHER(CXXConstructorDecl, isInterestingImplicitCtor) {
const CXXConstructorDecl *Declaration = Node.getCanonicalDecl();
return
+ // Skip constructors in system headers
+ !ASTIsInSystemHeader(Declaration->getASTContext(), *Declaration) &&
// Skip ignored namespaces and paths
!isInIgnoredNamespaceForImplicitCtor(Declaration) &&
!isIgnoredPathForImplicitCtor(Declaration) &&
@@ -1918,7 +1922,7 @@ void DiagnosticsMatcher::KungFuDeathGripChecker::run(
return;
}
- const Expr *E = IgnoreImplicit(D->getInit());
+ const Expr *E = IgnoreTrivials(D->getInit());
const CXXConstructExpr *CE = dyn_cast(E);
if (CE && CE->getNumArgs() == 0) {
// We don't report an error when we construct and don't use a nsCOMPtr /
@@ -1931,10 +1935,10 @@ void DiagnosticsMatcher::KungFuDeathGripChecker::run(
// We don't want to look at the single argument conversion constructors
// which are inbetween the declaration and the actual object which we are
// assigning into the nsCOMPtr/RefPtr. To do this, we repeatedly
- // IgnoreImplicit, then look at the expression. If it is one of these
+ // IgnoreTrivials, then look at the expression. If it is one of these
// conversion constructors, we ignore it and continue to dig.
while ((CE = dyn_cast(E)) && CE->getNumArgs() == 1) {
- E = IgnoreImplicit(CE->getArg(0));
+ E = IgnoreTrivials(CE->getArg(0));
}
// We allow taking a kungFuDeathGrip of `this` because it cannot change
diff --git a/build/clang-plugin/tests/TestKungFuDeathGrip.cpp b/build/clang-plugin/tests/TestKungFuDeathGrip.cpp
index 0b94d8a885b7..c9eef3ff2a5d 100644
--- a/build/clang-plugin/tests/TestKungFuDeathGrip.cpp
+++ b/build/clang-plugin/tests/TestKungFuDeathGrip.cpp
@@ -35,6 +35,7 @@ public:
nsCOMPtr never_referenced;
nsCOMPtr kfdg_t1(this);
nsCOMPtr kfdg_t2 = this;
+ nsCOMPtr kfdg_t3 = (this);
nsCOMPtr kfdg_m1(p); // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m1', or explicitly pass 'kfdg_m1' to `mozilla::Unused`}}
nsCOMPtr kfdg_m2 = p; // expected-error {{Unused "kungFuDeathGrip" 'nsCOMPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m2', or explicitly pass 'kfdg_m2' to `mozilla::Unused`}}
@@ -51,8 +52,9 @@ public:
RefPtr never_referenced2;
- RefPtr kfdg_t3(this);
- RefPtr kfdg_t4 = this;
+ RefPtr kfdg_t4(this);
+ RefPtr kfdg_t5 = this;
+ RefPtr kfdg_t6 = (this);
RefPtr kfdg_m5(p); // expected-error {{Unused "kungFuDeathGrip" 'RefPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m5', or explicitly pass 'kfdg_m5' to `mozilla::Unused`}}
RefPtr kfdg_m6 = p; // expected-error {{Unused "kungFuDeathGrip" 'RefPtr' objects constructed from members are prohibited}} expected-note {{Please switch all accesses to this member to go through 'kfdg_m6', or explicitly pass 'kfdg_m6' to `mozilla::Unused`}}
diff --git a/build/moz.configure/windows.configure b/build/moz.configure/windows.configure
index b9a3898a1d2f..4751c10d34df 100644
--- a/build/moz.configure/windows.configure
+++ b/build/moz.configure/windows.configure
@@ -335,8 +335,11 @@ def lib_path(target, vc_path, windows_sdk_dir, ucrt_sdk_dir, dia_sdk_dir):
atlmfc_dir = os.path.join(vc_path, 'atlmfc', 'lib', *vc_target)
if not os.path.isdir(atlmfc_dir):
- die('Cannot find the ATL/MFC libraries in the Visual C++ directory (%s). '
- 'Please install them.' % vc_path)
+ # For Visual Studio 2017
+ atlmfc_dir = os.path.join(vc_path, 'atlmfc', 'lib', sdk_target)
+ if not os.path.isdir(atlmfc_dir):
+ die('Cannot find the ATL/MFC libraries in the Visual C++ directory '
+ '(%s). Please install them.' % vc_path)
libs = []
diff --git a/caps/nsScriptSecurityManager.cpp b/caps/nsScriptSecurityManager.cpp
index f7fbc50c77e8..d06d081824f4 100644
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -326,9 +326,12 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
}
nsSecurityFlags securityFlags = loadInfo->GetSecurityMode();
- if (securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
- securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
- securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
+ // The data: inheritance flags should only apply to the initial load,
+ // not to loads that it might have redirected to.
+ if (loadInfo->RedirectChain().IsEmpty() &&
+ (securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
+ securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
+ securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)) {
nsCOMPtr uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
diff --git a/config/check_spidermonkey_style.py b/config/check_spidermonkey_style.py
index d66d6dc65844..ea6e726a095e 100644
--- a/config/check_spidermonkey_style.py
+++ b/config/check_spidermonkey_style.py
@@ -87,7 +87,7 @@ included_inclnames_to_ignore = set([
'unicode/udat.h', # ICU
'unicode/udatpg.h', # ICU
'unicode/uenum.h', # ICU
- 'unicode/unorm.h', # ICU
+ 'unicode/unorm2.h', # ICU
'unicode/unum.h', # ICU
'unicode/unumsys.h', # ICU
'unicode/ustring.h', # ICU
diff --git a/devtools/client/inspector/layout/layout.js b/devtools/client/inspector/layout/layout.js
index 2f7c6726c007..52c69fb3011c 100644
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -10,7 +10,7 @@ const { createFactory, createElement } = require("devtools/client/shared/vendor/
const { Provider } = require("devtools/client/shared/vendor/react-redux");
const { updateGrids } = require("./actions/grids");
-const App = createFactory(require("./components/app"));
+const App = createFactory(require("./components/App"));
const Store = require("./store");
const { LocalizationHelper } = require("devtools/shared/l10n");
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 40e0457f1f57..d9faa67c01e1 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -13785,6 +13785,7 @@ public:
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
+ bool aNoOpenerImplied,
bool aIsTrusted);
NS_IMETHOD Run() override
@@ -13801,6 +13802,7 @@ public:
mHandler->OnLinkClickSync(mContent, mURI,
mTargetSpec.get(), mFileName,
mPostDataStream, mHeadersDataStream,
+ mNoOpenerImplied,
nullptr, nullptr);
}
return NS_OK;
@@ -13815,6 +13817,7 @@ private:
nsCOMPtr mHeadersDataStream;
nsCOMPtr mContent;
PopupControlState mPopupState;
+ bool mNoOpenerImplied;
bool mIsTrusted;
};
@@ -13825,6 +13828,7 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
+ bool aNoOpenerImplied,
bool aIsTrusted)
: mHandler(aHandler)
, mURI(aURI)
@@ -13834,6 +13838,7 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
, mHeadersDataStream(aHeadersDataStream)
, mContent(aContent)
, mPopupState(mHandler->mScriptGlobal->GetPopupControlState())
+ , mNoOpenerImplied(aNoOpenerImplied)
, mIsTrusted(aIsTrusted)
{
}
@@ -13871,11 +13876,15 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
nsAutoString target;
nsCOMPtr browserChrome3 = do_GetInterface(mTreeOwner);
+ bool noOpenerImplied = false;
if (browserChrome3) {
nsCOMPtr linkNode = do_QueryInterface(aContent);
nsAutoString oldTarget(aTargetSpec);
rv = browserChrome3->OnBeforeLinkTraversal(oldTarget, aURI,
linkNode, mIsAppTab, target);
+ if (!oldTarget.Equals(target)) {
+ noOpenerImplied = true;
+ }
}
if (NS_FAILED(rv)) {
@@ -13884,7 +13893,8 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
nsCOMPtr ev =
new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName,
- aPostDataStream, aHeadersDataStream, aIsTrusted);
+ aPostDataStream, aHeadersDataStream, noOpenerImplied,
+ aIsTrusted);
return NS_DispatchToCurrentThread(ev);
}
@@ -13895,6 +13905,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
+ bool aNoOpenerImplied,
nsIDocShell** aDocShell,
nsIRequest** aRequest)
{
@@ -13960,6 +13971,9 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
}
}
+ if (aNoOpenerImplied) {
+ flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
+ }
}
// Get the owner document of the link that was clicked, this will be
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index 925115e95d8b..a723102c54bd 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -207,6 +207,7 @@ public:
const nsAString& aFileName,
nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0,
+ bool aNoOpenerImplied = false,
nsIDocShell** aDocShell = 0,
nsIRequest** aRequest = 0) override;
NS_IMETHOD OnOverLink(nsIContent* aContent,
diff --git a/docshell/base/nsILinkHandler.h b/docshell/base/nsILinkHandler.h
index 7cdcd566dfa0..62cbccb59a59 100644
--- a/docshell/base/nsILinkHandler.h
+++ b/docshell/base/nsILinkHandler.h
@@ -59,6 +59,7 @@ public:
* @param aFileName non-null when the link should be downloaded as the given file
* @param aPostDataStream the POST data to send
* @param aHeadersDataStream ???
+ * @param aNoOpenerImplied if the link implies "noopener"
* @param aDocShell (out-param) the DocShell that the request was opened on
* @param aRequest the request that was opened
*/
@@ -68,6 +69,7 @@ public:
const nsAString& aFileName,
nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0,
+ bool aNoOpenerImplied = false,
nsIDocShell** aDocShell = 0,
nsIRequest** aRequest = 0) = 0;
diff --git a/dom/animation/EffectCompositor.cpp b/dom/animation/EffectCompositor.cpp
index 458511d93d60..700eef0f298f 100644
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -86,6 +86,11 @@ FindAnimationsForCompositor(const nsIFrame* aFrame,
return false;
}
+ if (aFrame->StyleContext()->StyleSource().IsServoComputedValues()) {
+ NS_ERROR("stylo: cannot handle compositor-driven animations yet");
+ return false;
+ }
+
// The animation cascade will almost always be up-to-date by this point
// but there are some cases such as when we are restoring the refresh driver
// from test control after seeking where it might not be the case.
@@ -203,9 +208,11 @@ EffectCompositor::RequestRestyle(dom::Element* aElement,
if (aRestyleType == RestyleType::Layer) {
// Prompt layers to re-sync their animations.
- MOZ_ASSERT(mPresContext->RestyleManager()->IsGecko(),
- "stylo: Servo-backed style system should not be using "
+ if (mPresContext->RestyleManager()->IsServo()) {
+ NS_ERROR("stylo: Servo-backed style system should not be using "
"EffectCompositor");
+ return;
+ }
mPresContext->RestyleManager()->AsGecko()->IncrementAnimationGeneration();
EffectSet* effectSet =
EffectSet::GetEffectSet(aElement, aPseudoType);
diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp
index 82eb8250b0ba..4833789998a6 100644
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -170,11 +170,12 @@ DOMIntersectionObserver::UnlinkTarget(Element& aTarget)
if (!mObservationTargets.Contains(&aTarget)) {
return false;
}
- if (mObservationTargets.Count() == 1) {
+
+ mObservationTargets.RemoveEntry(&aTarget);
+ if (mObservationTargets.Count() == 0) {
Disconnect();
return false;
}
- mObservationTargets.RemoveEntry(&aTarget);
return true;
}
@@ -195,6 +196,8 @@ DOMIntersectionObserver::Disconnect()
if (!mConnected) {
return;
}
+
+ mConnected = false;
for (auto iter = mObservationTargets.Iter(); !iter.Done(); iter.Next()) {
Element* target = iter.Get()->GetKey();
target->UnregisterIntersectionObserver(this);
@@ -204,7 +207,6 @@ DOMIntersectionObserver::Disconnect()
nsIDocument* document = mOwner->GetExtantDoc();
document->RemoveIntersectionObserver(this);
}
- mConnected = false;
}
void
@@ -278,7 +280,10 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
if (rootFrame) {
nsPresContext* presContext = rootFrame->PresContext();
while (!presContext->IsRootContentDocument()) {
- presContext = rootFrame->PresContext()->GetParentPresContext();
+ presContext = presContext->GetParentPresContext();
+ if (!presContext) {
+ break;
+ }
rootFrame = presContext->PresShell()->GetRootScrollFrame();
}
root = rootFrame->GetContent()->AsElement();
diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h
index 1045ee4e5003..8b731a7110e1 100644
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -236,50 +236,10 @@ UnwrapObject(JSObject* obj, U& value)
PrototypeTraits::Depth);
}
-inline bool
-IsNotDateOrRegExp(JSContext* cx, JS::Handle obj,
- bool* notDateOrRegExp)
-{
- MOZ_ASSERT(obj);
-
- js::ESClass cls;
- if (!js::GetBuiltinClass(cx, obj, &cls)) {
- return false;
- }
-
- *notDateOrRegExp = cls != js::ESClass::Date && cls != js::ESClass::RegExp;
- return true;
-}
-
MOZ_ALWAYS_INLINE bool
-IsObjectValueConvertibleToDictionary(JSContext* cx,
- JS::Handle objVal,
- bool* convertible)
+IsConvertibleToDictionary(JS::Handle val)
{
- JS::Rooted obj(cx, &objVal.toObject());
- return IsNotDateOrRegExp(cx, obj, convertible);
-}
-
-MOZ_ALWAYS_INLINE bool
-IsConvertibleToDictionary(JSContext* cx, JS::Handle val,
- bool* convertible)
-{
- if (val.isNullOrUndefined()) {
- *convertible = true;
- return true;
- }
- if (!val.isObject()) {
- *convertible = false;
- return true;
- }
- return IsObjectValueConvertibleToDictionary(cx, val, convertible);
-}
-
-MOZ_ALWAYS_INLINE bool
-IsConvertibleToCallbackInterface(JSContext* cx, JS::Handle obj,
- bool* convertible)
-{
- return IsNotDateOrRegExp(cx, obj, convertible);
+ return val.isNullOrUndefined() || val.isObject();
}
// The items in the protoAndIfaceCache are indexed by the prototypes::id::ID,
@@ -2309,6 +2269,22 @@ AddStringToIDVector(JSContext* cx, JS::AutoIdVector& vector, const char* name)
AtomizeAndPinJSString(cx, *(vector[vector.length() - 1]).address(), name);
}
+// We use one constructor JSNative to represent all DOM interface objects (so
+// we can easily detect when we need to wrap them in an Xray wrapper). We store
+// the real JSNative in the mNative member of a JSNativeHolder in the
+// CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a
+// specific interface object. We also store the NativeProperties in the
+// JSNativeHolder.
+// Note that some interface objects are not yet a JSFunction but a normal
+// JSObject with a DOMJSClass, those do not use these slots.
+
+enum {
+ CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT = 0
+};
+
+bool
+Constructor(JSContext* cx, unsigned argc, JS::Value* vp);
+
// Implementation of the bits that XrayWrapper needs
/**
@@ -2382,6 +2358,9 @@ XrayGetNativeProto(JSContext* cx, JS::Handle obj,
} else {
protop.set(JS::GetRealmObjectPrototype(cx));
}
+ } else if (JS_ObjectIsFunction(cx, obj)) {
+ MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
+ protop.set(JS::GetRealmFunctionPrototype(cx));
} else {
const js::Class* clasp = js::GetObjectClass(obj);
MOZ_ASSERT(IsDOMIfaceAndProtoClass(clasp));
@@ -2448,22 +2427,6 @@ extern const js::ClassOps sBoringInterfaceObjectClassClassOps;
extern const js::ObjectOps sInterfaceObjectClassObjectOps;
-// We use one constructor JSNative to represent all DOM interface objects (so
-// we can easily detect when we need to wrap them in an Xray wrapper). We store
-// the real JSNative in the mNative member of a JSNativeHolder in the
-// CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a
-// specific interface object. We also store the NativeProperties in the
-// JSNativeHolder.
-// Note that some interface objects are not yet a JSFunction but a normal
-// JSObject with a DOMJSClass, those do not use these slots.
-
-enum {
- CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT = 0
-};
-
-bool
-Constructor(JSContext* cx, unsigned argc, JS::Value* vp);
-
inline bool
UseDOMXray(JSObject* obj)
{
@@ -2480,7 +2443,7 @@ HasConstructor(JSObject* obj)
return JS_IsNativeFunction(obj, Constructor) ||
js::GetObjectClass(obj)->getConstruct();
}
- #endif
+#endif
// Helpers for creating a const version of a type.
template
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 886c476517ee..917a504d2e93 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5783,30 +5783,24 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
exceptionCode=exceptionCode)
if failureCode is not None:
- if isDefinitelyObject:
- dictionaryTest = "IsObjectValueConvertibleToDictionary"
+ # This means we're part of an overload or union conversion, and
+ # should simply skip stuff if our value is not convertible to
+ # dictionary, instead of trying and throwing. If we're either
+ # isDefinitelyObject or isNullOrUndefined then we're convertible to
+ # dictionary and don't need to check here.
+ if isDefinitelyObject or isNullOrUndefined:
+ template = conversionCode
else:
- dictionaryTest = "IsConvertibleToDictionary"
-
- template = fill("""
- { // scope for isConvertible
- bool isConvertible;
- if (!${testConvertible}(cx, ${val}, &isConvertible)) {
- $*{exceptionCode}
- }
- if (!isConvertible) {
- $*{failureCode}
- }
-
- $*{conversionCode}
- }
-
- """,
- testConvertible=dictionaryTest,
- val=val,
- exceptionCode=exceptionCode,
- failureCode=failureCode,
- conversionCode=conversionCode)
+ template = fill(
+ """
+ if (!IsConvertibleToDictionary(${val})) {
+ $*{failureCode}
+ }
+ $*{conversionCode}
+ """,
+ val=val,
+ failureCode=failureCode,
+ conversionCode=conversionCode)
else:
template = conversionCode
@@ -8030,12 +8024,12 @@ class CGMethodCall(CGThing):
# 1) A platform object that's not a platform array object, being
# passed to an interface or "object" arg.
# 2) A Date object being passed to a Date or "object" arg.
- # 3) A RegExp object being passed to a RegExp or "object" arg.
- # 4) A callable object being passed to a callback or "object" arg.
- # 5) An iterable object being passed to a sequence arg.
- # 6) Any non-Date and non-RegExp object being passed to a
- # array or callback interface or dictionary or
- # "object" arg.
+ # XXXbz This is actually gone from the spec now, but we still
+ # have some APIs using Date.
+ # 3) A callable object being passed to a callback or "object" arg.
+ # 4) An iterable object being passed to a sequence arg.
+ # 5) Any object being passed to a array or callback interface or
+ # dictionary or "object" arg.
# First grab all the overloads that have a non-callback interface
# (which includes typed arrays and arraybuffers) at the
@@ -12591,14 +12585,8 @@ class CGDictionary(CGThing):
else:
body += dedent(
"""
- { // scope for isConvertible
- bool isConvertible;
- if (!IsConvertibleToDictionary(cx, val, &isConvertible)) {
- return false;
- }
- if (!isConvertible) {
- return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
- }
+ if (!IsConvertibleToDictionary(val)) {
+ return ThrowErrorMessage(cx, MSG_NOT_DICTIONARY, sourceDescription);
}
""")
diff --git a/dom/bindings/parser/tests/test_distinguishability.py b/dom/bindings/parser/tests/test_distinguishability.py
index d7780c1ffa11..9a6cf13c4ebb 100644
--- a/dom/bindings/parser/tests/test_distinguishability.py
+++ b/dom/bindings/parser/tests/test_distinguishability.py
@@ -163,7 +163,8 @@ def WebIDLTest(parser, harness):
"Promise", "Promise?",
"USVString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer",
"Uint8Array", "Uint16Array" ]
- # When we can parse Date and RegExp, we need to add them here.
+ # When we can parse Date, we need to add it here.
+ # XXXbz we can, and should really do that...
# Try to categorize things a bit to keep list lengths down
def allBut(list1, list2):
diff --git a/dom/bindings/test/chrome.ini b/dom/bindings/test/chrome.ini
index fdf90d300bd4..9fdbd7fd30ba 100644
--- a/dom/bindings/test/chrome.ini
+++ b/dom/bindings/test/chrome.ini
@@ -19,3 +19,4 @@ skip-if = e10s # prerendering doesn't work in e10s yet
skip-if = e10s # prerendering doesn't work in e10s yet
[test_bug1123516_maplikesetlikechrome.xul]
skip-if = debug == false
+[test_bug1287912.html]
diff --git a/dom/bindings/test/test_bug1287912.html b/dom/bindings/test/test_bug1287912.html
new file mode 100644
index 000000000000..ae72b23165f0
--- /dev/null
+++ b/dom/bindings/test/test_bug1287912.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+ Test for Bug 1287912
+
+
+
+
+Mozilla Bug 1287912
+
+
+
+
+
+
+
+
+
diff --git a/dom/bindings/test/test_exception_messages.html b/dom/bindings/test/test_exception_messages.html
index a0f0cabe63a2..9d5378f23fc0 100644
--- a/dom/bindings/test/test_exception_messages.html
+++ b/dom/bindings/test/test_exception_messages.html
@@ -44,9 +44,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=882653
[ 'document.createTreeWalker(document, 0xFFFFFFFF, { acceptNode: 5 }).nextNode()',
"Property 'acceptNode' is not callable.",
"non-callable callback interface operation property" ],
- [ '(new TextDecoder).decode(new Uint8Array(), new RegExp())',
+ [ '(new TextDecoder).decode(new Uint8Array(), 5)',
"Argument 2 of TextDecoder.decode can't be converted to a dictionary.",
- "regexp passed for a dictionary" ],
+ "primitive passed for a dictionary" ],
[ 'URL.createObjectURL(null, null)',
"Argument 1 is not valid for any of the 2-argument overloads of URL.createObjectURL.",
"overload resolution failure" ],
diff --git a/dom/canvas/WebGL2Context.h b/dom/canvas/WebGL2Context.h
index 52609c13e5aa..144984f355f8 100644
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -121,7 +121,7 @@ public:
{
const char funcName[] = "compressedTexImage3D";
const uint8_t funcDims = 3;
- const TexImageSourceAdapter src(anySrc, viewElemOffset, viewElemLengthOverride);
+ const TexImageSourceAdapter src(&anySrc, viewElemOffset, viewElemLengthOverride);
CompressedTexImage(funcName, funcDims, target, level, internalFormat, width,
height, depth, border, src);
}
@@ -135,7 +135,7 @@ public:
{
const char funcName[] = "compressedTexSubImage3D";
const uint8_t funcDims = 3;
- const TexImageSourceAdapter src(anySrc, viewElemOffset, viewElemLengthOverride);
+ const TexImageSourceAdapter src(&anySrc, viewElemOffset, viewElemLengthOverride);
CompressedTexSubImage(funcName, funcDims, target, level, xOffset, yOffset,
zOffset, width, height, depth, unpackFormat, src);
}
@@ -159,7 +159,7 @@ public:
GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat,
GLenum unpackType, const T& anySrc, ErrorResult& out_error)
{
- const TexImageSourceAdapter src(anySrc, &out_error);
+ const TexImageSourceAdapter src(&anySrc, &out_error);
TexImage3D(target, level, internalFormat, width, height, depth, border,
unpackFormat, unpackType, src);
}
@@ -169,7 +169,7 @@ public:
GLenum unpackType, const dom::ArrayBufferView& view,
GLuint viewElemOffset, ErrorResult&)
{
- const TexImageSourceAdapter src(view, viewElemOffset);
+ const TexImageSourceAdapter src(&view, viewElemOffset);
TexImage3D(target, level, internalFormat, width, height, depth, border,
unpackFormat, unpackType, src);
}
@@ -194,7 +194,7 @@ public:
GLenum unpackFormat, GLenum unpackType, const T& anySrc,
ErrorResult& out_error)
{
- const TexImageSourceAdapter src(anySrc, &out_error);
+ const TexImageSourceAdapter src(&anySrc, &out_error);
TexSubImage3D(target, level, xOffset, yOffset, zOffset, width, height, depth,
unpackFormat, unpackType, src);
}
@@ -212,7 +212,7 @@ public:
return;
const auto& srcView = maybeSrcView.Value();
- const TexImageSourceAdapter src(srcView, srcElemOffset);
+ const TexImageSourceAdapter src(&srcView, srcElemOffset);
TexSubImage3D(target, level, xOffset, yOffset, zOffset, width, height, depth,
unpackFormat, unpackType, src);
}
diff --git a/dom/canvas/WebGL2ContextBuffers.cpp b/dom/canvas/WebGL2ContextBuffers.cpp
index fd5c986089c3..81812e8f9745 100644
--- a/dom/canvas/WebGL2ContextBuffers.cpp
+++ b/dom/canvas/WebGL2ContextBuffers.cpp
@@ -31,15 +31,6 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
if (!writeBuffer)
return;
- if (readBuffer->mNumActiveTFOs ||
- writeBuffer->mNumActiveTFOs)
- {
- ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
- " object.",
- funcName);
- return;
- }
-
if (!ValidateNonNegative(funcName, "readOffset", readOffset) ||
!ValidateNonNegative(funcName, "writeOffset", writeOffset) ||
!ValidateNonNegative(funcName, "size", size))
@@ -129,21 +120,6 @@ WebGL2Context::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
////
- if (buffer->mNumActiveTFOs) {
- ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
- " object.",
- funcName);
- return;
- }
-
- if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER &&
- mBoundTransformFeedback->mIsActive)
- {
- ErrorInvalidOperation("%s: Currently bound transform feedback is active.",
- funcName);
- return;
- }
-
if (!CheckedInt(byteLen).isValid()) {
ErrorOutOfMemory("%s: Size too large.", funcName);
return;
diff --git a/dom/canvas/WebGLBuffer.cpp b/dom/canvas/WebGLBuffer.cpp
index f47176d73ea2..2647bc33cbac 100644
--- a/dom/canvas/WebGLBuffer.cpp
+++ b/dom/canvas/WebGLBuffer.cpp
@@ -18,15 +18,12 @@ WebGLBuffer::WebGLBuffer(WebGLContext* webgl, GLuint buf)
, mContent(Kind::Undefined)
, mUsage(LOCAL_GL_STATIC_DRAW)
, mByteLength(0)
- , mNumActiveTFOs(0)
- , mBoundForTF(false)
{
mContext->mBuffers.insertBack(this);
}
WebGLBuffer::~WebGLBuffer()
{
- MOZ_ASSERT(!mNumActiveTFOs);
DeleteOnce();
}
@@ -111,13 +108,6 @@ WebGLBuffer::BufferData(GLenum target, size_t size, const void* data, GLenum usa
if (!ValidateBufferUsageEnum(mContext, funcName, usage))
return;
- if (mNumActiveTFOs) {
- mContext->ErrorInvalidOperation("%s: Buffer is bound to an active transform"
- " feedback object.",
- funcName);
- return;
- }
-
const auto& gl = mContext->gl;
gl->MakeCurrent();
const ScopedLazyBind lazyBind(gl, target, this);
@@ -220,15 +210,6 @@ WebGLBuffer::IsElementArrayUsedWithMultipleTypes() const
bool
WebGLBuffer::ValidateCanBindToTarget(const char* funcName, GLenum target)
{
- const bool wouldBeTF = (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER);
- if (mWebGLRefCnt && wouldBeTF != mBoundForTF) {
- mContext->ErrorInvalidOperation("%s: Buffers cannot be simultaneously bound to "
- " transform feedback and bound elsewhere.",
- funcName);
- return false;
- }
- mBoundForTF = wouldBeTF;
-
/* https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.1
*
* In the WebGL 2 API, buffers have their WebGL buffer type
diff --git a/dom/canvas/WebGLBuffer.h b/dom/canvas/WebGLBuffer.h
index 3bb1db1071f9..cb4c87edc33b 100644
--- a/dom/canvas/WebGLBuffer.h
+++ b/dom/canvas/WebGLBuffer.h
@@ -79,8 +79,6 @@ protected:
GLenum mUsage;
size_t mByteLength;
UniquePtr mCache;
- size_t mNumActiveTFOs;
- bool mBoundForTF;
};
} // namespace mozilla
diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp
index e05e612d43e9..bbfa26e6097b 100644
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -120,6 +120,7 @@ WebGLContext::WebGLContext()
, mMaxFetchedInstances(0)
, mLayerIsMirror(false)
, mBypassShaderValidation(false)
+ , mBuffersForUB_Dirty(true)
, mContextLossHandler(this)
, mNeedsFakeNoAlpha(false)
, mNeedsFakeNoDepth(false)
@@ -262,6 +263,7 @@ WebGLContext::DestroyResourcesAndContext()
mQuerySlot_TimeElapsed = nullptr;
mIndexedUniformBufferBindings.clear();
+ OnUBIndexedBindingsChanged();
//////
@@ -2570,6 +2572,42 @@ WebGLContext::ValidateArrayBufferView(const char* funcName,
return true;
}
+////
+
+const decltype(WebGLContext::mBuffersForUB)&
+WebGLContext::BuffersForUB() const
+{
+ if (mBuffersForUB_Dirty) {
+ mBuffersForUB.clear();
+ for (const auto& cur : mIndexedUniformBufferBindings) {
+ if (cur.mBufferBinding) {
+ mBuffersForUB.insert(cur.mBufferBinding.get());
+ }
+ }
+ mBuffersForUB_Dirty = false;
+ }
+ return mBuffersForUB;
+}
+
+////
+
+bool
+WebGLContext::ValidateForNonTransformFeedback(const char* funcName, WebGLBuffer* buffer)
+{
+ if (!mBoundTransformFeedback)
+ return true;
+
+ const auto& buffersForTF = mBoundTransformFeedback->BuffersForTF();
+ if (buffersForTF.count(buffer)) {
+ ErrorInvalidOperation("%s: Specified WebGLBuffer is currently bound for transform"
+ " feedback.",
+ funcName);
+ return false;
+ }
+
+ return true;
+}
+
////////////////////////////////////////////////////////////////////////////////
// XPCOM goop
diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h
index e00c2fd8e441..e7634474361e 100644
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -220,40 +220,40 @@ protected:
struct TexImageSourceAdapter final : public TexImageSource
{
- TexImageSourceAdapter(const dom::Nullable& maybeView,
+ TexImageSourceAdapter(const dom::Nullable* maybeView,
ErrorResult*)
{
- if (!maybeView.IsNull()) {
- mView = &(maybeView.Value());
+ if (!maybeView->IsNull()) {
+ mView = &(maybeView->Value());
}
}
- TexImageSourceAdapter(const dom::ArrayBufferView& view, ErrorResult*) {
- mView = &view;
+ TexImageSourceAdapter(const dom::ArrayBufferView* view, ErrorResult*) {
+ mView = view;
}
- TexImageSourceAdapter(const dom::ArrayBufferView& view, GLuint viewElemOffset,
+ TexImageSourceAdapter(const dom::ArrayBufferView* view, GLuint viewElemOffset,
GLuint viewElemLengthOverride = 0)
{
- mView = &view;
+ mView = view;
mViewElemOffset = viewElemOffset;
mViewElemLengthOverride = viewElemLengthOverride;
}
- TexImageSourceAdapter(WebGLsizeiptr pboOffset, GLuint ignored1, GLuint ignored2 = 0) {
- mPboOffset = &pboOffset;
+ TexImageSourceAdapter(const WebGLsizeiptr* pboOffset, GLuint ignored1, GLuint ignored2 = 0) {
+ mPboOffset = pboOffset;
}
- TexImageSourceAdapter(WebGLsizeiptr pboOffset, ErrorResult* ignored) {
- mPboOffset = &pboOffset;
+ TexImageSourceAdapter(const WebGLsizeiptr* pboOffset, ErrorResult* ignored) {
+ mPboOffset = pboOffset;
}
- TexImageSourceAdapter(const dom::ImageData& imageData, ErrorResult*) {
- mImageData = &imageData;
+ TexImageSourceAdapter(const dom::ImageData* imageData, ErrorResult*) {
+ mImageData = imageData;
}
- TexImageSourceAdapter(const dom::Element& domElem, ErrorResult* const out_error) {
- mDomElem = &domElem;
+ TexImageSourceAdapter(const dom::Element* domElem, ErrorResult* const out_error) {
+ mDomElem = domElem;
mOut_error = out_error;
}
};
@@ -1026,7 +1026,7 @@ public:
const char funcName[] = "compressedTexImage2D";
const uint8_t funcDims = 2;
const GLsizei depth = 1;
- const TexImageSourceAdapter src(anySrc, viewElemOffset, viewElemLengthOverride);
+ const TexImageSourceAdapter src(&anySrc, viewElemOffset, viewElemLengthOverride);
CompressedTexImage(funcName, funcDims, target, level, internalFormat, width,
height, depth, border, src);
}
@@ -1041,7 +1041,7 @@ public:
const uint8_t funcDims = 2;
const GLint zOffset = 0;
const GLsizei depth = 1;
- const TexImageSourceAdapter src(anySrc, viewElemOffset, viewElemLengthOverride);
+ const TexImageSourceAdapter src(&anySrc, viewElemOffset, viewElemLengthOverride);
CompressedTexSubImage(funcName, funcDims, target, level, xOffset, yOffset,
zOffset, width, height, depth, unpackFormat, src);
}
@@ -1115,7 +1115,7 @@ public:
GLsizei height, GLint border, GLenum unpackFormat, GLenum unpackType,
const T& anySrc, ErrorResult& out_error)
{
- const TexImageSourceAdapter src(anySrc, &out_error);
+ const TexImageSourceAdapter src(&anySrc, &out_error);
TexImage2D(target, level, internalFormat, width, height, border, unpackFormat,
unpackType, src);
}
@@ -1125,7 +1125,7 @@ public:
const dom::ArrayBufferView& view, GLuint viewElemOffset,
ErrorResult&)
{
- const TexImageSourceAdapter src(view, viewElemOffset);
+ const TexImageSourceAdapter src(&view, viewElemOffset);
TexImage2D(target, level, internalFormat, width, height, border, unpackFormat,
unpackType, src);
}
@@ -1155,7 +1155,7 @@ public:
GLsizei width, GLsizei height, GLenum unpackFormat,
GLenum unpackType, const T& anySrc, ErrorResult& out_error)
{
- const TexImageSourceAdapter src(anySrc, &out_error);
+ const TexImageSourceAdapter src(&anySrc, &out_error);
TexSubImage2D(target, level, xOffset, yOffset, width, height, unpackFormat,
unpackType, src);
}
@@ -1165,7 +1165,7 @@ public:
GLenum unpackType, const dom::ArrayBufferView& view,
GLuint viewElemOffset, ErrorResult&)
{
- const TexImageSourceAdapter src(view, viewElemOffset);
+ const TexImageSourceAdapter src(&view, viewElemOffset);
TexSubImage2D(target, level, xOffset, yOffset, width, height, unpackFormat,
unpackType, src);
}
@@ -1580,7 +1580,9 @@ protected:
}
WebGLRefPtr* ValidateBufferSlot(const char* funcName, GLenum target);
+public:
WebGLBuffer* ValidateBufferSelection(const char* funcName, GLenum target);
+protected:
IndexedBufferBinding* ValidateIndexedBufferSlot(const char* funcName, GLenum target,
GLuint index);
@@ -1596,6 +1598,8 @@ protected:
return true;
}
+ bool ValidateForNonTransformFeedback(const char* funcName, WebGLBuffer* buffer);
+
public:
template
bool ValidateNonNull(const char* funcName, const dom::Nullable& maybe) {
@@ -1754,6 +1758,17 @@ protected:
////////////////////////////////////
+private:
+ mutable bool mBuffersForUB_Dirty;
+ mutable std::set mBuffersForUB;
+
+public:
+ void OnUBIndexedBindingsChanged() const { mBuffersForUB_Dirty = true; }
+ const decltype(mBuffersForUB)& BuffersForUB() const;
+
+ ////////////////////////////////////
+
+protected:
// Generic Vertex Attributes
UniquePtr mVertexAttribType;
GLfloat mVertexAttrib0Vector[4];
diff --git a/dom/canvas/WebGLContextBuffers.cpp b/dom/canvas/WebGLContextBuffers.cpp
index c3fc7035beb4..03bd50934b39 100644
--- a/dom/canvas/WebGLContextBuffers.cpp
+++ b/dom/canvas/WebGLContextBuffers.cpp
@@ -75,6 +75,9 @@ WebGLContext::ValidateBufferSelection(const char* funcName, GLenum target)
return nullptr;
}
+ if (!ValidateForNonTransformFeedback(funcName, buffer.get()))
+ return nullptr;
+
return buffer.get();
}
@@ -212,6 +215,15 @@ WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
if (buffer) {
buffer->SetContentAfterBind(target);
}
+
+ switch (target) {
+ case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
+ mBoundTransformFeedback->OnIndexedBindingsChanged();
+ break;
+ case LOCAL_GL_UNIFORM:
+ OnUBIndexedBindingsChanged();
+ break;
+ }
}
void
@@ -296,6 +308,15 @@ WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
if (buffer) {
buffer->SetContentAfterBind(target);
}
+
+ switch (target) {
+ case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
+ mBoundTransformFeedback->OnIndexedBindingsChanged();
+ break;
+ case LOCAL_GL_UNIFORM:
+ OnUBIndexedBindingsChanged();
+ break;
+ }
}
////////////////////////////////////////
@@ -383,13 +404,6 @@ WebGLContext::BufferSubDataImpl(GLenum target, WebGLsizeiptr dstByteOffset,
if (!buffer)
return;
- if (buffer->mNumActiveTFOs) {
- ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
- " object.",
- "bufferSubData");
- return;
- }
-
if (!buffer->ValidateRange(funcName, dstByteOffset, dataLen))
return;
diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp
index d5411bb566e9..38447699b62c 100644
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -19,6 +19,8 @@
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
+#include
+
namespace mozilla {
// For a Tegra workaround.
@@ -300,6 +302,16 @@ WebGLContext::DrawArrays_check(const char* funcName, GLenum mode, GLint first,
////////////////////////////////////////
+template
+static bool
+DoSetsIntersect(const std::set& a, const std::set& b)
+{
+ std::vector intersection;
+ std::set_intersection(a.begin(), a.end(), b.begin(), b.end(),
+ std::back_inserter(intersection));
+ return bool(intersection.size());
+}
+
class ScopedDrawHelper final
{
WebGLContext* const mWebGL;
@@ -343,7 +355,7 @@ public:
////
// Check UBO sizes.
- const auto& linkInfo = webgl->mActiveProgramLinkInfo;
+ const auto& linkInfo = mWebGL->mActiveProgramLinkInfo;
for (const auto& cur : linkInfo->uniformBlocks) {
const auto& dataSize = cur->mDataSize;
const auto& binding = cur->mBinding;
@@ -366,6 +378,22 @@ public:
////
+ const auto& tfo = mWebGL->mBoundTransformFeedback;
+ if (tfo) {
+ const auto& buffersForTF = tfo->BuffersForTF();
+ const auto& buffersForUB = mWebGL->BuffersForUB();
+ if (DoSetsIntersect(buffersForTF, buffersForUB)) {
+ mWebGL->ErrorInvalidOperation("%s: At least one WebGLBuffer is bound for"
+ " both transform feedback and as a uniform"
+ " buffer.",
+ funcName);
+ *out_error = true;
+ return;
+ }
+ }
+
+ ////
+
mWebGL->RunContextLossTimer();
}
diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp
index ae1d72cb25b7..6f091d999e9e 100644
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1462,41 +1462,33 @@ void
WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
GLenum type, WebGLsizeiptr offset, ErrorResult& out_error)
{
+ const char funcName[] = "readPixels";
if (!ReadPixels_SharedPrecheck(&out_error))
return;
- if (!mBoundPixelPackBuffer) {
- ErrorInvalidOperation("readPixels: PIXEL_PACK_BUFFER must not be null.");
+ const auto& buffer = ValidateBufferSelection(funcName, LOCAL_GL_PIXEL_PACK_BUFFER);
+ if (!buffer)
return;
- }
-
- if (mBoundPixelPackBuffer->mNumActiveTFOs) {
- ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
- " object.",
- "readPixels");
- return;
- }
//////
- if (offset < 0) {
- ErrorInvalidValue("readPixels: offset must not be negative.");
+ if (!ValidateNonNegative(funcName, "offset", offset))
return;
- }
{
const auto bytesPerType = webgl::BytesPerPixel({LOCAL_GL_RED, type});
if (offset % bytesPerType != 0) {
- ErrorInvalidOperation("readPixels: `offset` must be divisible by the size"
- " a `type` in bytes.");
+ ErrorInvalidOperation("%s: `offset` must be divisible by the size of `type`"
+ " in bytes.",
+ funcName);
return;
}
}
//////
- const auto bytesAvailable = mBoundPixelPackBuffer->ByteLength();
+ const auto bytesAvailable = buffer->ByteLength();
const auto checkedBytesAfterOffset = CheckedUint32(bytesAvailable) - offset;
uint32_t bytesAfterOffset = 0;
@@ -1505,7 +1497,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
}
gl->MakeCurrent();
- const ScopedLazyBind lazyBind(gl, LOCAL_GL_PIXEL_PACK_BUFFER, mBoundPixelPackBuffer);
+ const ScopedLazyBind lazyBind(gl, LOCAL_GL_PIXEL_PACK_BUFFER, buffer);
ReadPixelsImpl(x, y, width, height, format, type, (void*)offset, bytesAfterOffset);
}
diff --git a/dom/canvas/WebGLProgram.cpp b/dom/canvas/WebGLProgram.cpp
index 50ffd530a0b0..8abf4edb6e4d 100644
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -1444,7 +1444,7 @@ WebGLProgram::TransformFeedbackVaryings(const dom::Sequence& varyings,
GLuint maxAttribs = 0;
gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
&maxAttribs);
- if (varyings.Length() >= maxAttribs) {
+ if (varyings.Length() > maxAttribs) {
mContext->ErrorInvalidValue("%s: Length of `varyings` exceeds %s.",
funcName,
"TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
diff --git a/dom/canvas/WebGLTextureUpload.cpp b/dom/canvas/WebGLTextureUpload.cpp
index 0f76a9c6114b..b65510162c1a 100644
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -185,14 +185,19 @@ FromView(WebGLContext* webgl, const char* funcName, TexImageTarget target,
static UniquePtr
FromPboOffset(WebGLContext* webgl, const char* funcName, TexImageTarget target,
- uint32_t width, uint32_t height, uint32_t depth, WebGLsizeiptr pboOffset,
- size_t availBufferBytes)
+ uint32_t width, uint32_t height, uint32_t depth, WebGLsizeiptr pboOffset)
{
if (pboOffset < 0) {
webgl->ErrorInvalidValue("%s: offset cannot be negative.", funcName);
return nullptr;
}
+ const auto& buffer = webgl->ValidateBufferSelection(funcName,
+ LOCAL_GL_PIXEL_UNPACK_BUFFER);
+ if (!buffer)
+ return nullptr;
+
+ size_t availBufferBytes = buffer->ByteLength();
if (size_t(pboOffset) > availBufferBytes) {
webgl->ErrorInvalidOperation("%s: Offset is passed end of buffer.", funcName);
return nullptr;
@@ -366,25 +371,12 @@ WebGLContext::From(const char* funcName, TexImageTarget target, GLsizei rawWidth
}
if (src.mPboOffset) {
- if (!mBoundPixelUnpackBuffer) {
- ErrorInvalidOperation("%s: PACK_BUFFER must be non-null.", funcName);
- return nullptr;
- }
-
- if (mBoundPixelUnpackBuffer->mNumActiveTFOs) {
- ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
- " object.",
- funcName);
- return nullptr;
- }
-
- const auto& availBytes = mBoundPixelUnpackBuffer->ByteLength();
return FromPboOffset(this, funcName, target, width, height, depth,
- *(src.mPboOffset), availBytes);
+ *(src.mPboOffset));
}
if (mBoundPixelUnpackBuffer) {
- ErrorInvalidOperation("%s: PACK_BUFFER must be null.", funcName);
+ ErrorInvalidOperation("%s: PIXEL_UNPACK_BUFFER must be null.", funcName);
return nullptr;
}
@@ -1370,25 +1362,12 @@ WebGLContext::FromCompressed(const char* funcName, TexImageTarget target,
}
if (src.mPboOffset) {
- if (!mBoundPixelUnpackBuffer) {
- ErrorInvalidOperation("%s: PACK_BUFFER must be non-null.", funcName);
- return nullptr;
- }
-
- if (mBoundPixelUnpackBuffer->mNumActiveTFOs) {
- ErrorInvalidOperation("%s: Buffer is bound to an active transform feedback"
- " object.",
- funcName);
- return nullptr;
- }
-
- const auto& availBytes = mBoundPixelUnpackBuffer->ByteLength();
return FromPboOffset(this, funcName, target, width, height, depth,
- *(src.mPboOffset), availBytes);
+ *(src.mPboOffset));
}
if (mBoundPixelUnpackBuffer) {
- ErrorInvalidOperation("%s: PACK_BUFFER must be null.", funcName);
+ ErrorInvalidOperation("%s: PIXEL_UNPACK_BUFFER must be null.", funcName);
return nullptr;
}
diff --git a/dom/canvas/WebGLTransformFeedback.cpp b/dom/canvas/WebGLTransformFeedback.cpp
index 82ec8c648f01..2fa2752be879 100644
--- a/dom/canvas/WebGLTransformFeedback.cpp
+++ b/dom/canvas/WebGLTransformFeedback.cpp
@@ -17,6 +17,7 @@ WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* webgl, GLuint tf)
, mIndexedBindings(webgl->mGLMaxTransformFeedbackSeparateAttribs)
, mIsPaused(false)
, mIsActive(false)
+ , mBuffersForTF_Dirty(true)
{
mContext->mTransformFeedbacks.insertBack(this);
}
@@ -36,6 +37,28 @@ WebGLTransformFeedback::Delete()
removeFrom(mContext->mTransformFeedbacks);
}
+////
+
+const decltype(WebGLTransformFeedback::mBuffersForTF)&
+WebGLTransformFeedback::BuffersForTF() const
+{
+ // The generic bind point cannot incur undefined read/writes because otherwise it
+ // would be impossible to read back from this. The spec implies that readback from
+ // the TRANSFORM_FEEDBACK target is possible, just not simultaneously with being
+ // "bound or in use for transform feedback".
+ // Therefore, only the indexed bindings of the TFO count.
+ if (mBuffersForTF_Dirty) {
+ mBuffersForTF.clear();
+ for (const auto& cur : mIndexedBindings) {
+ if (cur.mBufferBinding) {
+ mBuffersForTF.insert(cur.mBufferBinding.get());
+ }
+ }
+ mBuffersForTF_Dirty = false;
+ }
+ return mBuffersForTF;
+}
+
////////////////////////////////////////
void
@@ -107,13 +130,6 @@ WebGLTransformFeedback::BeginTransformFeedback(GLenum primMode)
////
- for (const auto& cur : mIndexedBindings) {
- const auto& buffer = cur.mBufferBinding;
- if (buffer) {
- buffer->mNumActiveTFOs++;
- }
- }
-
mActive_Program->mNumActiveTFOs++;
}
@@ -139,13 +155,6 @@ WebGLTransformFeedback::EndTransformFeedback()
////
- for (const auto& cur : mIndexedBindings) {
- const auto& buffer = cur.mBufferBinding;
- if (buffer) {
- buffer->mNumActiveTFOs--;
- }
- }
-
mActive_Program->mNumActiveTFOs--;
}
diff --git a/dom/canvas/WebGLTransformFeedback.h b/dom/canvas/WebGLTransformFeedback.h
index 34747af74efb..e681242291a0 100644
--- a/dom/canvas/WebGLTransformFeedback.h
+++ b/dom/canvas/WebGLTransformFeedback.h
@@ -37,6 +37,9 @@ private:
MOZ_INIT_OUTSIDE_CTOR size_t mActive_VertPosition;
MOZ_INIT_OUTSIDE_CTOR size_t mActive_VertCapacity;
+ mutable bool mBuffersForTF_Dirty;
+ mutable std::set mBuffersForTF;
+
public:
WebGLTransformFeedback(WebGLContext* webgl, GLuint tf);
private:
@@ -50,6 +53,11 @@ public:
WebGLContext* GetParentObject() const { return mContext; }
virtual JSObject* WrapObject(JSContext*, JS::Handle) override;
+ ////
+
+ void OnIndexedBindingsChanged() const { mBuffersForTF_Dirty = true; }
+ const decltype(mBuffersForTF)& BuffersForTF() const;
+
// GL Funcs
void BeginTransformFeedback(GLenum primMode);
void EndTransformFeedback();
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html
index a9d13496abd1..35532834c99f 100644
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html
@@ -61,6 +61,8 @@ shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "0");
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "0");
gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4, gl.STATIC_DRAW);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
+
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer1");
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "0");
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "0");
@@ -97,11 +99,13 @@ shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "8");
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "4");
gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4, gl.STATIC_DRAW);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer3");
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "8");
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "4");
gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 12, gl.STATIC_DRAW);
+wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer3");
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "8");
shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "4");
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html
index 57a8a8fbf3a2..206f07f0689f 100644
--- a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html
@@ -88,7 +88,7 @@ var testBindingFn = function(firstBindFn, secondBindFn, firstTarget, secondTarge
wtu.glErrorShouldBe(gl, gl.NO_ERROR, messagePrefix + "WORK");
else
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, messagePrefix + "FAIL");
-
+ /*
if ((firstTarget == gl.TRANSFORM_FEEDBACK_BUFFER && secondTarget != gl.TRANSFORM_FEEDBACK_BUFFER) ||
(firstTarget != gl.TRANSFORM_FEEDBACK_BUFFER && secondTarget == gl.TRANSFORM_FEEDBACK_BUFFER)) {
bind(firstBindFn, firstTarget, buffer);
@@ -98,6 +98,7 @@ var testBindingFn = function(firstBindFn, secondBindFn, firstTarget, secondTarge
+ " and simultaneously binding buffer with " + secondBindFn + " to gl." + secondTargetStr + " should FAIL";
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, message);
}
+ */
}
var testBinding = function(firstTarget, secondTarget) {
diff --git a/dom/filesystem/Directory.h b/dom/filesystem/Directory.h
index 09473b2bb851..5814b95994c5 100644
--- a/dom/filesystem/Directory.h
+++ b/dom/filesystem/Directory.h
@@ -144,6 +144,12 @@ public:
bool
ClonableToDifferentThreadOrProcess() const;
+ nsIFile*
+ GetInternalNsIFile() const
+ {
+ return mFile;
+ }
+
private:
Directory(nsISupports* aParent,
nsIFile* aFile,
diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp
index 0088b57563a9..27d0fcb54b9d 100644
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -829,7 +829,7 @@ HTMLFormElement::SubmitSubmission(HTMLFormSubmission* aFormSubmission)
rv = linkHandler->OnLinkClickSync(this, actionURI,
target.get(),
NullString(),
- postDataStream, nullptr,
+ postDataStream, nullptr, false,
getter_AddRefs(docShell),
getter_AddRefs(mSubmittingRequest));
NS_ENSURE_SUBMIT_SUCCESS(rv);
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
index d4f6ee507758..42af7c563546 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -485,28 +485,37 @@ namespace {
* where the file picker can create Blobs.
*/
static already_AddRefed
-DOMFileOrDirectoryToLocalFile(const OwningFileOrDirectory& aData)
+LastUsedDirectory(const OwningFileOrDirectory& aData)
{
- nsString path;
-
if (aData.IsFile()) {
- ErrorResult rv;
- aData.GetAsFile()->GetMozFullPathInternal(path, rv);
- if (rv.Failed() || path.IsEmpty()) {
- rv.SuppressException();
+ nsAutoString path;
+ ErrorResult error;
+ aData.GetAsFile()->GetMozFullPathInternal(path, error);
+ if (error.Failed() || path.IsEmpty()) {
+ error.SuppressException();
return nullptr;
}
- } else {
- MOZ_ASSERT(aData.IsDirectory());
- aData.GetAsDirectory()->GetFullRealPath(path);
+
+ nsCOMPtr localFile;
+ nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
+ getter_AddRefs(localFile));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return nullptr;
+ }
+
+ nsCOMPtr parentFile;
+ rv = localFile->GetParent(getter_AddRefs(parentFile));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return nullptr;
+ }
+
+ return parentFile.forget();
}
- nsCOMPtr localFile;
- nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
- getter_AddRefs(localFile));
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return nullptr;
- }
+ MOZ_ASSERT(aData.IsDirectory());
+
+ nsCOMPtr localFile = aData.GetAsDirectory()->GetInternalNsIFile();
+ MOZ_ASSERT(localFile);
return localFile.forget();
}
@@ -616,12 +625,9 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
}
// Store the last used directory using the content pref service:
- nsCOMPtr file =
- DOMFileOrDirectoryToLocalFile(newFilesOrDirectories[0]);
+ nsCOMPtr lastUsedDir = LastUsedDirectory(newFilesOrDirectories[0]);
- if (file) {
- nsCOMPtr lastUsedDir;
- file->GetParent(getter_AddRefs(lastUsedDir));
+ if (lastUsedDir) {
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc(), lastUsedDir);
}
@@ -994,7 +1000,7 @@ HTMLInputElement::InitFilePicker(FilePickerType aType)
filePicker->AppendFilters(nsIFilePicker::filterAll);
}
- // Set default directry and filename
+ // Set default directory and filename
nsAutoString defaultName;
const nsTArray& oldFiles =
@@ -1005,15 +1011,11 @@ HTMLInputElement::InitFilePicker(FilePickerType aType)
if (!oldFiles.IsEmpty() &&
aType != FILE_PICKER_DIRECTORY) {
- nsString path;
+ nsAutoString path;
- nsCOMPtr localFile = DOMFileOrDirectoryToLocalFile(oldFiles[0]);
- if (localFile) {
- nsCOMPtr parentFile;
- nsresult rv = localFile->GetParent(getter_AddRefs(parentFile));
- if (NS_SUCCEEDED(rv)) {
- filePicker->SetDisplayDirectory(parentFile);
- }
+ nsCOMPtr parentFile = LastUsedDirectory(oldFiles[0]);
+ if (parentFile) {
+ filePicker->SetDisplayDirectory(parentFile);
}
// Unfortunately nsIFilePicker doesn't allow multiple files to be
diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp
index c5a4792bef57..bd2f872167d2 100644
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -600,10 +600,6 @@ GMPCapability::Supports(const nsTArray& aCapabilities,
if (!WMFDecoderModule::HasH264()) {
continue;
}
- } else if (capabilities.mAPIName.EqualsLiteral(GMP_API_AUDIO_DECODER)) {
- if (!WMFDecoderModule::HasAAC()) {
- continue;
- }
}
}
#endif
diff --git a/dom/smil/nsSMILAnimationController.cpp b/dom/smil/nsSMILAnimationController.cpp
index f447509311bb..8350e3163fb9 100644
--- a/dom/smil/nsSMILAnimationController.cpp
+++ b/dom/smil/nsSMILAnimationController.cpp
@@ -321,6 +321,12 @@ nsSMILAnimationController::DoSample(bool aSkipUnchangedContainers)
bool isStyleFlushNeeded = mResampleNeeded;
mResampleNeeded = false;
+
+ if (mDocument->IsStyledByServo()) {
+ NS_ERROR("stylo: SMIL animations not supported yet");
+ return;
+ }
+
// Set running sample flag -- do this before flushing styles so that when we
// flush styles we don't end up requesting extra samples
AutoRestore autoRestoreRunningSample(mRunningSample);
diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h
index 222157ab358b..419a5fef48fc 100644
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -12,6 +12,7 @@
#include "Matrix.h"
#include "Quaternion.h"
#include "UserData.h"
+#include
// GenericRefCountedBase allows us to hold on to refcounted objects of any type
// (contrary to RefCounted which requires knowing the type T) and, in particular,
@@ -630,6 +631,10 @@ struct Glyph
Point mPosition;
};
+static inline bool operator==(const Glyph& aOne, const Glyph& aOther) {
+ return aOne.mIndex == aOther.mIndex && aOne.mPosition == aOther.mPosition;
+}
+
/** This class functions as a glyph buffer that can be drawn to a DrawTarget.
* @todo XXX - This should probably contain the guts of gfxTextRun in the future as
* roc suggested. But for now it's a simple container for a glyph vector.
@@ -664,7 +669,7 @@ struct GlyphMetrics
* at a particular size. It is passed into text drawing calls to describe
* the font used for the drawing call.
*/
-class ScaledFont : public RefCounted
+class ScaledFont : public external::AtomicRefCounted
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont)
@@ -778,6 +783,7 @@ public:
virtual BackendType GetBackendType() const = 0;
virtual bool IsRecording() const { return false; }
+ virtual bool IsCaptureDT() const { return false; }
/**
* Returns a SourceSurface which is a snapshot of the current contents of the DrawTarget.
@@ -1272,6 +1278,17 @@ protected:
class DrawTargetCapture : public DrawTarget
{
+public:
+ virtual bool IsCaptureDT() const { return true; }
+
+ /**
+ * Returns true if the recording only contains FillGlyph calls with
+ * a single font and color. Returns the list of Glyphs along with
+ * the font and color as outparams if so.
+ */
+ virtual bool ContainsOnlyColoredGlyphs(RefPtr& aScaledFont,
+ Color& aColor,
+ std::vector& aGlyphs) = 0;
};
class DrawEventRecorder : public RefCounted
diff --git a/gfx/2d/DrawCommand.h b/gfx/2d/DrawCommand.h
index eb415c70a931..83bbad8c1f96 100644
--- a/gfx/2d/DrawCommand.h
+++ b/gfx/2d/DrawCommand.h
@@ -46,14 +46,14 @@ public:
virtual bool GetAffectedRect(Rect& aDeviceRect, const Matrix& aTransform) const { return false; }
+ CommandType GetType() { return mType; }
+
protected:
explicit DrawingCommand(CommandType aType)
: mType(aType)
{
}
- CommandType GetType() { return mType; }
-
private:
CommandType mType;
};
@@ -418,6 +418,7 @@ private:
class FillGlyphsCommand : public DrawingCommand
{
+ friend class DrawTargetCaptureImpl;
public:
FillGlyphsCommand(ScaledFont* aFont,
const GlyphBuffer& aBuffer,
@@ -553,6 +554,7 @@ public:
class SetTransformCommand : public DrawingCommand
{
+ friend class DrawTargetCaptureImpl;
public:
explicit SetTransformCommand(const Matrix& aTransform)
: DrawingCommand(CommandType::SETTRANSFORM)
diff --git a/gfx/2d/DrawTargetCapture.cpp b/gfx/2d/DrawTargetCapture.cpp
index f0584c427cc6..c6599275f9a6 100644
--- a/gfx/2d/DrawTargetCapture.cpp
+++ b/gfx/2d/DrawTargetCapture.cpp
@@ -197,5 +197,63 @@ DrawTargetCaptureImpl::ReplayToDrawTarget(DrawTarget* aDT, const Matrix& aTransf
}
}
+bool
+DrawTargetCaptureImpl::ContainsOnlyColoredGlyphs(RefPtr& aScaledFont,
+ Color& aColor,
+ std::vector& aGlyphs)
+{
+ uint8_t* start = &mDrawCommandStorage.front();
+ uint8_t* current = start;
+
+ while (current < start + mDrawCommandStorage.size()) {
+ DrawingCommand* command =
+ reinterpret_cast(current + sizeof(uint32_t));
+ current += *(uint32_t*)current;
+
+ if (command->GetType() != CommandType::FILLGLYPHS &&
+ command->GetType() != CommandType::SETTRANSFORM) {
+ return false;
+ }
+
+ if (command->GetType() == CommandType::SETTRANSFORM) {
+ SetTransformCommand* transform = static_cast(command);
+ if (transform->mTransform != Matrix()) {
+ return false;
+ }
+ continue;
+ }
+
+ FillGlyphsCommand* fillGlyphs = static_cast(command);
+ if (aScaledFont && fillGlyphs->mFont != aScaledFont) {
+ return false;
+ }
+ aScaledFont = fillGlyphs->mFont;
+
+ Pattern& pat = fillGlyphs->mPattern;
+
+ if (pat.GetType() != PatternType::COLOR) {
+ return false;
+ }
+
+ ColorPattern* colorPat = static_cast(&pat);
+ if (aColor != Color() && colorPat->mColor != aColor) {
+ return false;
+ }
+ aColor = colorPat->mColor;
+
+ if (fillGlyphs->mOptions.mCompositionOp != CompositionOp::OP_OVER ||
+ fillGlyphs->mOptions.mAlpha != 1.0f) {
+ return false;
+ }
+
+ //TODO: Deal with AA on the DrawOptions, and the GlyphRenderingOptions
+
+ aGlyphs.insert(aGlyphs.end(),
+ fillGlyphs->mGlyphs.begin(),
+ fillGlyphs->mGlyphs.end());
+ }
+ return true;
+}
+
} // namespace gfx
} // namespace mozilla
diff --git a/gfx/2d/DrawTargetCapture.h b/gfx/2d/DrawTargetCapture.h
index a60e07b56b12..af6d71d20fd3 100644
--- a/gfx/2d/DrawTargetCapture.h
+++ b/gfx/2d/DrawTargetCapture.h
@@ -27,6 +27,8 @@ public:
virtual BackendType GetBackendType() const { return mRefDT->GetBackendType(); }
virtual DrawTargetType GetType() const { return mRefDT->GetType(); }
+ virtual bool IsCaptureDT() const { return true; }
+
virtual already_AddRefed Snapshot();
virtual void DetachAllSnapshots();
@@ -136,6 +138,8 @@ public:
void ReplayToDrawTarget(DrawTarget* aDT, const Matrix& aTransform);
+ bool ContainsOnlyColoredGlyphs(RefPtr& aScaledFont, Color& aColor, std::vector& aGlyphs);
+
protected:
~DrawTargetCaptureImpl();
diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h
index e45aa7040c1f..fd838f5a809a 100644
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -25,6 +25,7 @@
#include "mozilla/layers/LayersTypes.h"
#include "nsRect.h"
#include "nsRegion.h"
+#include "mozilla/Array.h"
#include
@@ -1268,6 +1269,42 @@ struct ParamTraits
}
};
+template <>
+struct ParamTraits
+{
+ typedef mozilla::gfx::Glyph paramType;
+ static void Write(Message* aMsg, const paramType& aParam) {
+ WriteParam(aMsg, aParam.mIndex);
+ WriteParam(aMsg, aParam.mPosition);
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
+ return (ReadParam(aMsg, aIter, &aResult->mIndex) &&
+ ReadParam(aMsg, aIter, &aResult->mPosition)
+ );
+ }
+};
+
+template
+struct ParamTraits>
+{
+ typedef mozilla::Array paramType;
+ static void Write(Message* aMsg, const paramType& aParam) {
+ for (size_t i = 0; i < Length; i++) {
+ WriteParam(aMsg, aParam[i]);
+ }
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) {
+ for (size_t i = 0; i < Length; i++) {
+ if (!ReadParam(aMsg, aIter, &aResult[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
} /* namespace IPC */
#endif /* __GFXMESSAGEUTILS_H__ */
diff --git a/gfx/layers/LayerTreeInvalidation.cpp b/gfx/layers/LayerTreeInvalidation.cpp
index a5fdb2df008c..f2061f57d770 100644
--- a/gfx/layers/LayerTreeInvalidation.cpp
+++ b/gfx/layers/LayerTreeInvalidation.cpp
@@ -479,9 +479,9 @@ public:
static ImageHost* GetImageHost(Layer* aLayer)
{
- LayerComposite* composite = aLayer->AsLayerComposite();
- if (composite) {
- return static_cast(composite->GetCompositableHost());
+ HostLayer* compositor = aLayer->AsHostLayer();
+ if (compositor) {
+ return static_cast(compositor->GetCompositableHost());
}
return nullptr;
}
@@ -609,6 +609,8 @@ CloneLayerTreePropertiesInternal(Layer* aRoot, bool aIsMask /* = false */)
case Layer::TYPE_READBACK:
case Layer::TYPE_SHADOW:
case Layer::TYPE_PAINTED:
+ case Layer::TYPE_TEXT:
+ case Layer::TYPE_BORDER:
return MakeUnique(aRoot);
}
diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp
index c07eba481ca6..d621c408e8cc 100644
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -576,7 +576,7 @@ Layer::CanUseOpaqueSurface()
const Maybe&
Layer::GetLocalClipRect()
{
- if (LayerComposite* shadow = AsLayerComposite()) {
+ if (HostLayer* shadow = AsHostLayer()) {
return shadow->GetShadowClipRect();
}
return GetClipRect();
@@ -585,7 +585,7 @@ Layer::GetLocalClipRect()
const LayerIntRegion&
Layer::GetLocalVisibleRegion()
{
- if (LayerComposite* shadow = AsLayerComposite()) {
+ if (HostLayer* shadow = AsHostLayer()) {
return shadow->GetShadowVisibleRegion();
}
return GetVisibleRegion();
@@ -782,7 +782,7 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect)
}
if (GetLocalVisibleRegion().IsEmpty() &&
- !(AsLayerComposite() && AsLayerComposite()->NeedToDrawCheckerboarding())) {
+ !(AsHostLayer() && AsHostLayer()->NeedToDrawCheckerboarding())) {
// When our visible region is empty, our parent may not have created the
// intermediate surface that we would require for correct clipping; however,
// this does not matter since we are invisible.
@@ -887,7 +887,7 @@ Layer::GetTransformTyped() const
Matrix4x4
Layer::GetLocalTransform()
{
- if (LayerComposite* shadow = AsLayerComposite())
+ if (HostLayer* shadow = AsHostLayer())
return shadow->GetShadowTransform();
else
return GetTransform();
@@ -941,7 +941,7 @@ float
Layer::GetLocalOpacity()
{
float opacity = mOpacity;
- if (LayerComposite* shadow = AsLayerComposite())
+ if (HostLayer* shadow = AsHostLayer())
opacity = shadow->GetShadowOpacity();
return std::min(std::max(opacity, 0.0f), 1.0f);
}
@@ -1661,7 +1661,7 @@ LayerManager::BeginTabSwitch()
mTabSwitchStart = TimeStamp::Now();
}
-static void PrintInfo(std::stringstream& aStream, LayerComposite* aLayerComposite);
+static void PrintInfo(std::stringstream& aStream, HostLayer* aLayerComposite);
#ifdef MOZ_DUMP_PAINTING
template
@@ -1702,8 +1702,8 @@ Layer::Dump(std::stringstream& aStream, const char* aPrefix,
bool aDumpHtml, bool aSorted)
{
#ifdef MOZ_DUMP_PAINTING
- bool dumpCompositorTexture = gfxEnv::DumpCompositorTextures() && AsLayerComposite() &&
- AsLayerComposite()->GetCompositableHost();
+ bool dumpCompositorTexture = gfxEnv::DumpCompositorTextures() && AsHostLayer() &&
+ AsHostLayer()->GetCompositableHost();
bool dumpClientTexture = gfxEnv::DumpPaint() && AsShadowableLayer() &&
AsShadowableLayer()->GetCompositableClient();
nsCString layerId(Name());
@@ -1723,7 +1723,7 @@ Layer::Dump(std::stringstream& aStream, const char* aPrefix,
#ifdef MOZ_DUMP_PAINTING
if (dumpCompositorTexture) {
- AsLayerComposite()->GetCompositableHost()->Dump(aStream, aPrefix, aDumpHtml);
+ AsHostLayer()->GetCompositableHost()->Dump(aStream, aPrefix, aDumpHtml);
} else if (dumpClientTexture) {
if (aDumpHtml) {
aStream << nsPrintfCString(R"(