diff --git a/Makefile.in b/Makefile.in index 012f69bebfc8..845585fe4092 100644 --- a/Makefile.in +++ b/Makefile.in @@ -38,19 +38,12 @@ DIST_GARBAGE = config.cache config.log config.status* config-defs.h \ .mozconfig.mk ifndef MOZ_PROFILE_USE -# Automation builds should always have a new buildid, but for the sake of not -# re-linking libxul on every incremental build we do not enforce this for -# developer builds. Tests always need a new buildid as well. -ifneq (,$(MOZ_AUTOMATION)$(MOZ_BUILD_DATE)$(TEST_MOZBUILD)) +ifneq (mobile/android,$(MOZ_BUILD_APP)) $(MDDEPDIR)/buildid.h.stub $(MDDEPDIR)/source-repo.h.stub: FORCE endif -# Additionally, provide a dummy target during tests, because -# faster/rules.mk will expect these targets to exist. -ifdef TEST_MOZBUILD source-repo.h: $(MDDEPDIR)/source-repo.h.stub buildid.h: $(MDDEPDIR)/buildid.h.stub endif -endif BUILD_BACKEND_FILES := $(addprefix backend.,$(addsuffix Backend,$(BUILD_BACKENDS))) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 715223bc3829..fbb0a48d7109 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -343,13 +343,8 @@ pref("browser.urlbar.openintab", false); pref("browser.urlbar.usepreloadedtopurls.enabled", false); pref("browser.urlbar.usepreloadedtopurls.expire_days", 14); -// Toggle the new work in progress Address Bar code. Enable it on Nightly and Beta, -// not on Release yet. -#ifdef EARLY_BETA_OR_EARLIER +// Enable the new Address Bar code. pref("browser.urlbar.quantumbar", true); -#else -pref("browser.urlbar.quantumbar", false); -#endif pref("browser.altClickSave", false); diff --git a/browser/base/content/browser-sync.js b/browser/base/content/browser-sync.js index fa95595cd4de..239a5c7a4f71 100644 --- a/browser/base/content/browser-sync.js +++ b/browser/base/content/browser-sync.js @@ -16,8 +16,6 @@ ChromeUtils.defineModuleGetter(this, "Weave", const MIN_STATUS_ANIMATION_DURATION = 1600; -const FXA_NO_AVATAR_ZEROS = "00000000000000000000000000000000"; - var gSync = { _initialized: false, // The last sync start time. Used to calculate the leftover animation time @@ -327,11 +325,7 @@ var gSync = { stateValue = "unverified"; } else if (state.status === UIState.STATUS_SIGNED_IN) { stateValue = "signedin"; - // Firefox Account specifies a `default` avatar image that uses the convention - // of all 0s in url. The default used in the design of the toolbar menu is - // different from the one provided by Firefox Account. Perform a check and only - // change avatar *if* this is not a default avatar. - if (state.avatarURL && !state.avatarURL.includes(FXA_NO_AVATAR_ZEROS)) { + if (state.avatarURL && !state.avatarIsDefault) { // The user has specified a custom avatar, attempt to load the image on all the menu buttons. const bgImage = `url("${state.avatarURL}")`; let img = new Image(); @@ -373,7 +367,7 @@ var gSync = { emitFxaToolbarTelemetry(type, panel) { if (UIState.isReady() && panel) { const state = UIState.get(); - const hasAvatar = state.avatarURL && !state.avatarURL.includes(FXA_NO_AVATAR_ZEROS); + const hasAvatar = state.avatarURL && !state.avatarIsDefault; let extraOptions = {"fxa_status": state.status, "fxa_avatar": hasAvatar ? "true" : "false"}; // When the fxa avatar panel is within the Firefox app menu, @@ -430,21 +424,6 @@ var gSync = { this.appMenuLabel.setAttribute("label", state.displayName || state.email); this.appMenuLabel.classList.add("subviewbutton-nav"); this.appMenuStatus.removeAttribute("tooltiptext"); - - if (state.avatarURL) { - let bgImage = "url(\"" + state.avatarURL + "\")"; - this.appMenuAvatar.style.listStyleImage = bgImage; - - let img = new Image(); - img.onerror = () => { - // Clear the image if it has trouble loading. Since this callback is asynchronous - // we check to make sure the image is still the same before we clear it. - if (this.appMenuAvatar.style.listStyleImage === bgImage) { - this.appMenuAvatar.style.removeProperty("list-style-image"); - } - }; - img.src = state.avatarURL; - } }, updateState(state) { diff --git a/browser/base/content/test/performance/browser_preferences_usage.js b/browser/base/content/test/performance/browser_preferences_usage.js index b0cf45c2fcd7..11c713b028c0 100644 --- a/browser/base/content/test/performance/browser_preferences_usage.js +++ b/browser/base/content/test/performance/browser_preferences_usage.js @@ -86,10 +86,6 @@ add_task(async function startup() { min: 200, max: 350, }, - "layout.css.prefixes.webkit": { - min: 135, - max: 170, - }, "layout.css.dpi": { min: 45, max: 81, diff --git a/browser/base/content/test/sync/browser_sync.js b/browser/base/content/test/sync/browser_sync.js index 3a2227990f64..b9a194252f0f 100644 --- a/browser/base/content/test/sync/browser_sync.js +++ b/browser/base/content/test/sync/browser_sync.js @@ -42,14 +42,13 @@ add_task(async function test_ui_state_signedin() { checkPanelUIStatusBar({ label: "Foo Bar", fxastatus: "signedin", - avatarURL: "https://foo.bar", syncing: false, syncNowTooltip: lastSyncTooltip, }); checkRemoteTabsPanel("PanelUI-remotetabs-main", false); checkMenuBarItem("sync-syncnowitem"); checkFxaToolbarButtonPanel("PanelUI-fxa-menu"); - checkFxaToolbarButtonAvatar("signedin"); + checkFxAAvatar("signedin"); gSync.relativeTimeFormat = origRelativeTimeFormat; }); @@ -92,7 +91,7 @@ add_task(async function test_ui_state_unconfigured() { checkRemoteTabsPanel("PanelUI-remotetabs-setupsync"); checkMenuBarItem("sync-setup"); checkFxaToolbarButtonPanel("PanelUI-fxa-signin"); - checkFxaToolbarButtonAvatar("not_configured"); + checkFxAAvatar("not_configured"); }); add_task(async function test_ui_state_unverified() { @@ -111,14 +110,13 @@ add_task(async function test_ui_state_unverified() { label: expectedLabel, tooltip: tooltipText, fxastatus: "unverified", - avatarURL: null, syncing: false, syncNowTooltip: tooltipText, }); checkRemoteTabsPanel("PanelUI-remotetabs-unverified", false); checkMenuBarItem("sync-unverifieditem"); checkFxaToolbarButtonPanel("PanelUI-fxa-unverified"); - checkFxaToolbarButtonAvatar("unverified"); + checkFxAAvatar("unverified"); }); add_task(async function test_ui_state_loginFailed() { @@ -135,21 +133,19 @@ add_task(async function test_ui_state_loginFailed() { label: expectedLabel, tooltip: tooltipText, fxastatus: "login-failed", - avatarURL: null, syncing: false, syncNowTooltip: tooltipText, }); checkRemoteTabsPanel("PanelUI-remotetabs-reauthsync", false); checkMenuBarItem("sync-reauthitem"); checkFxaToolbarButtonPanel("PanelUI-fxa-unverified"); - checkFxaToolbarButtonAvatar("unverified"); + checkFxAAvatar("unverified"); }); -function checkPanelUIStatusBar({label, tooltip, fxastatus, avatarURL, syncing, syncNowTooltip}) { +function checkPanelUIStatusBar({label, tooltip, fxastatus, syncing, syncNowTooltip}) { let labelNode = document.getElementById("appMenu-fxa-label"); let tooltipNode = document.getElementById("appMenu-fxa-status"); let statusNode = document.getElementById("appMenu-fxa-container"); - let avatar = document.getElementById("appMenu-fxa-avatar"); is(labelNode.getAttribute("label"), label, "fxa label has the right value"); if (tooltipNode.getAttribute("tooltiptext")) { @@ -160,11 +156,6 @@ function checkPanelUIStatusBar({label, tooltip, fxastatus, avatarURL, syncing, s } else { ok(!statusNode.hasAttribute("fxastatus"), "fxastatus is unset"); } - if (avatarURL) { - is(avatar.style.listStyleImage, `url("${avatarURL}")`, "fxa avatar URL is set"); - } else { - ok(!statusNode.style.listStyleImage, "fxa avatar URL is unset"); - } } function checkRemoteTabsPanel(expectedShownItemId, syncing, syncNowTooltip) { @@ -212,15 +203,20 @@ async function checkFxaToolbarButtonPanel(expectedShownItemId) { } // fxaStatus is one of 'not_configured', 'unverified', or 'signedin'. -function checkFxaToolbarButtonAvatar(fxaStatus) { - const avatar = document.getElementById("fxa-avatar-image"); - const avatarURL = getComputedStyle(avatar).listStyleImage; - const expected = { - not_configured: "url(\"chrome://browser/skin/fxa/avatar-empty-badged.svg\")", - unverified: "url(\"chrome://browser/skin/fxa/avatar-confirm.svg\")", - signedin: "url(\"chrome://browser/skin/fxa/avatar.svg\")", - }; - ok(avatarURL == expected[fxaStatus], `expected avatar URL to be ${expected[fxaStatus]}, but got ${avatarURL}`); +function checkFxAAvatar(fxaStatus) { + const avatarContainers = [ + document.getElementById("appMenu-fxa-avatar"), + document.getElementById("fxa-avatar-image"), + ]; + for (const avatar of avatarContainers) { + const avatarURL = getComputedStyle(avatar).listStyleImage; + const expected = { + not_configured: "url(\"chrome://browser/skin/fxa/avatar-empty-badged.svg\")", + unverified: "url(\"chrome://browser/skin/fxa/avatar-confirm.svg\")", + signedin: "url(\"chrome://browser/skin/fxa/avatar.svg\")", + }; + ok(avatarURL == expected[fxaStatus], `expected avatar URL to be ${expected[fxaStatus]}, got ${avatarURL}`); + } } // Only one item displayed at a time. diff --git a/browser/components/extensions/test/browser/browser-common.ini b/browser/components/extensions/test/browser/browser-common.ini index ad32e054a60a..3ae32a440f71 100644 --- a/browser/components/extensions/test/browser/browser-common.ini +++ b/browser/components/extensions/test/browser/browser-common.ini @@ -201,6 +201,7 @@ skip-if = !e10s [browser_ext_tabs_discarded.js] [browser_ext_tabs_duplicate.js] [browser_ext_tabs_events.js] +skip-if = true # Bug 1521363 [browser_ext_tabs_events_order.js] [browser_ext_tabs_executeScript.js] skip-if = (verify && !debug && (os == 'mac')) diff --git a/browser/components/newtab/data/content/assets/sync-devices.svg b/browser/components/newtab/data/content/assets/sync-devices.svg index 0bb13eb5a22d..fcf3f662caad 100644 --- a/browser/components/newtab/data/content/assets/sync-devices.svg +++ b/browser/components/newtab/data/content/assets/sync-devices.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/browser/components/preferences/in-content/sync.js b/browser/components/preferences/in-content/sync.js index 835ccd22db86..5d4059ff8511 100644 --- a/browser/components/preferences/in-content/sync.js +++ b/browser/components/preferences/in-content/sync.js @@ -321,7 +321,7 @@ var gSyncPane = { } else { fxaLoginStatus.removeAttribute("hasName"); } - if (state.avatarURL) { + if (state.avatarURL && !state.avatarIsDefault) { let bgImage = "url(\"" + state.avatarURL + "\")"; let profileImageElement = document.querySelector("#fxaLoginVerified > .fxaProfileImage"); profileImageElement.style.listStyleImage = bgImage; diff --git a/browser/themes/shared/customizableui/panelUI.inc.css b/browser/themes/shared/customizableui/panelUI.inc.css index d02fe2d15c66..8f642fc784d8 100644 --- a/browser/themes/shared/customizableui/panelUI.inc.css +++ b/browser/themes/shared/customizableui/panelUI.inc.css @@ -568,7 +568,9 @@ toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton #appMenu-fxa-avatar { pointer-events: none; - list-style-image: url(chrome://browser/skin/fxa/default-avatar.svg); + list-style-image: var(--avatar-image-url); + -moz-context-properties: fill; + fill: currentColor; } /* Handle different UI states. */ @@ -697,26 +699,31 @@ toolbarbutton[constrain-size="true"][cui-areatype="menu-panel"] > .toolbarbutton --avatar-image-url: url(chrome://browser/skin/fxa/avatar.svg); } -:root[fxastatus="unverified"] #fxa-avatar-image { - list-style-image: url(chrome://browser/skin/fxa/avatar-confirm.svg); +:root[fxastatus="unverified"] { + --avatar-image-url: url(chrome://browser/skin/fxa/avatar-confirm.svg); } -:root[fxastatus="not_configured"] #fxa-avatar-image { - list-style-image: url(chrome://browser/skin/fxa/avatar-empty.svg); +:root[fxastatus="not_configured"] { + --avatar-image-url: url(chrome://browser/skin/fxa/avatar-empty.svg); } -:root[fxastatus="not_configured"][fxa_avatar_badged="badged"] #fxa-avatar-image { - list-style-image: url(chrome://browser/skin/fxa/avatar-empty-badged.svg); +:root[fxastatus="not_configured"][fxa_avatar_badged="badged"] { + --avatar-image-url: url(chrome://browser/skin/fxa/avatar-empty-badged.svg); } :root:not([fxatoolbarmenu]) #fxa-toolbar-menu-button { display: none; } +#fxa-menu-avatar, +#fxa-avatar-image { + list-style-image: var(--avatar-image-url); +} + +/* Non-signedin statuses icons are not totally round. */ :root[fxastatus="signedin"] #fxa-menu-avatar, :root[fxastatus="signedin"] #fxa-avatar-image { border-radius: 50%; - list-style-image: var(--avatar-image-url); } :root[fxastatus="signedin"] #PanelUI-fxa-signin, @@ -796,7 +803,7 @@ panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow { .fxaChooseWhatToSyncDevices { height: 102px; width: 201px; - list-style-image: url(chrome://browser/skin/fxa/choose-what-to-sync-devices.svg); + list-style-image: url(chrome://browser/skin/fxa/sync-devices.svg); } .fxaGraphicMail { @@ -806,7 +813,7 @@ panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow { } #PanelUI-remotetabs { - --panel-ui-sync-illustration-height: 91px; + --panel-ui-sync-illustration-height: 141px; } .PanelUI-fxa-signin-instruction-label, @@ -885,7 +892,7 @@ panelmultiview[mainViewId="PanelUI-fxa"] #PanelUI-remotetabs-syncnow { /* If you change the margin here, the min-height of the synced tabs panel (e.g. #PanelUI-remotetabs[mainview] #PanelUI-remotetabs-setupsync, etc) may need adjusting (see bug 1248506) */ - width: 104px; + width: 204px; height: var(--panel-ui-sync-illustration-height); margin: 38px 0 15px; -moz-context-properties: fill; diff --git a/browser/themes/shared/fxa/avatar-color.svg b/browser/themes/shared/fxa/avatar-color.svg new file mode 100644 index 000000000000..b39f00a1936b --- /dev/null +++ b/browser/themes/shared/fxa/avatar-color.svg @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/browser/themes/shared/fxa/choose-what-to-sync-devices.svg b/browser/themes/shared/fxa/choose-what-to-sync-devices.svg deleted file mode 100644 index 4ef7caf058b9..000000000000 --- a/browser/themes/shared/fxa/choose-what-to-sync-devices.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/browser/themes/shared/fxa/default-avatar.svg b/browser/themes/shared/fxa/default-avatar.svg deleted file mode 100644 index 540234911544..000000000000 --- a/browser/themes/shared/fxa/default-avatar.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/browser/themes/shared/fxa/sync-devices.svg b/browser/themes/shared/fxa/sync-devices.svg new file mode 100644 index 000000000000..5c9ff7b03cc1 --- /dev/null +++ b/browser/themes/shared/fxa/sync-devices.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/themes/shared/fxa/sync-illustration-issue.svg b/browser/themes/shared/fxa/sync-illustration-issue.svg index a2e9e0df2300..9fdfb1e65dd9 100644 --- a/browser/themes/shared/fxa/sync-illustration-issue.svg +++ b/browser/themes/shared/fxa/sync-illustration-issue.svg @@ -1,57 +1,52 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/browser/themes/shared/fxa/sync-illustration.svg b/browser/themes/shared/fxa/sync-illustration.svg index ca9b5290de5d..155d2a40092d 100755 --- a/browser/themes/shared/fxa/sync-illustration.svg +++ b/browser/themes/shared/fxa/sync-illustration.svg @@ -1,56 +1,50 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + diff --git a/browser/themes/shared/incontentprefs/fxa-avatar.svg b/browser/themes/shared/incontentprefs/fxa-avatar.svg deleted file mode 100755 index 17accc5b28e6..000000000000 --- a/browser/themes/shared/incontentprefs/fxa-avatar.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/browser/themes/shared/incontentprefs/preferences.inc.css b/browser/themes/shared/incontentprefs/preferences.inc.css index f5e673f00927..b4ff9cb04cd4 100644 --- a/browser/themes/shared/incontentprefs/preferences.inc.css +++ b/browser/themes/shared/incontentprefs/preferences.inc.css @@ -578,7 +578,7 @@ button > hbox > label { height: 80px; border-radius: 50%; border: 1px solid transparent; - list-style-image: url("chrome://browser/skin/preferences/in-content/fxa-avatar.svg"); + list-style-image: url(chrome://browser/skin/fxa/avatar-color.svg); margin-inline-end: 24px; -moz-user-focus: normal; } @@ -634,7 +634,7 @@ button > hbox > label { } .fxaSyncIllustration { - list-style-image: url("chrome://browser/skin/preferences/in-content/sync-devices.svg"); + list-style-image: url(chrome://browser/skin/fxa/sync-devices.svg); width: 312px; height: 136px; } diff --git a/browser/themes/shared/incontentprefs/sync-devices.svg b/browser/themes/shared/incontentprefs/sync-devices.svg deleted file mode 100644 index 3bbe9c795bde..000000000000 --- a/browser/themes/shared/incontentprefs/sync-devices.svg +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/browser/themes/shared/jar.inc.mn b/browser/themes/shared/jar.inc.mn index 0e4bc9918724..a51b153db695 100644 --- a/browser/themes/shared/jar.inc.mn +++ b/browser/themes/shared/jar.inc.mn @@ -110,7 +110,6 @@ skin/classic/browser/preferences/in-content/critters-postcard.jpg (../shared/incontentprefs/critters-postcard.jpg) skin/classic/browser/preferences/in-content/face-sad.svg (../shared/incontentprefs/face-sad.svg) skin/classic/browser/preferences/in-content/face-smile.svg (../shared/incontentprefs/face-smile.svg) - skin/classic/browser/preferences/in-content/fxa-avatar.svg (../shared/incontentprefs/fxa-avatar.svg) skin/classic/browser/preferences/in-content/fxaPairDevice.css (../shared/incontentprefs/fxaPairDevice.css) skin/classic/browser/preferences/in-content/general.svg (../shared/incontentprefs/general.svg) skin/classic/browser/preferences/in-content/logo-android.svg (../shared/incontentprefs/logo-android.svg) @@ -124,22 +123,21 @@ skin/classic/browser/preferences/in-content/search.css (../shared/incontentprefs/search.css) skin/classic/browser/preferences/in-content/search.svg (../shared/incontentprefs/search.svg) skin/classic/browser/preferences/in-content/siteDataSettings.css (../shared/incontentprefs/siteDataSettings.css) - skin/classic/browser/preferences/in-content/sync-devices.svg (../shared/incontentprefs/sync-devices.svg) skin/classic/browser/preferences/in-content/sync.svg (../shared/incontentprefs/sync.svg) skin/classic/browser/preferences/in-content/syncDisconnect.css (../shared/incontentprefs/syncDisconnect.css) * skin/classic/browser/preferences/in-content/containers.css (../shared/incontentprefs/containers.css) * skin/classic/browser/preferences/containers.css (../shared/preferences/containers.css) - skin/classic/browser/fxa/default-avatar.svg (../shared/fxa/default-avatar.svg) skin/classic/browser/fxa/fxa-spinner.svg (../shared/fxa/fxa-spinner.svg) skin/classic/browser/fxa/sync-illustration.svg (../shared/fxa/sync-illustration.svg) skin/classic/browser/fxa/sync-illustration-issue.svg (../shared/fxa/sync-illustration-issue.svg) skin/classic/browser/fxa/avatar.svg (../shared/fxa/avatar.svg) + skin/classic/browser/fxa/avatar-color.svg (../shared/fxa/avatar-color.svg) skin/classic/browser/fxa/avatar-confirm.svg (../shared/fxa/avatar-confirm.svg) skin/classic/browser/fxa/avatar-empty.svg (../shared/fxa/avatar-empty.svg) skin/classic/browser/fxa/avatar-empty-badged.svg (../shared/fxa/avatar-empty-badged.svg) skin/classic/browser/fxa/graphic-mail.svg (../shared/fxa/graphic-mail.svg) - skin/classic/browser/fxa/choose-what-to-sync-devices.svg (../shared/fxa/choose-what-to-sync-devices.svg) + skin/classic/browser/fxa/sync-devices.svg (../shared/fxa/sync-devices.svg) skin/classic/browser/accessibility.svg (../shared/icons/accessibility.svg) skin/classic/browser/accessibility-active.svg (../shared/icons/accessibility-active.svg) diff --git a/browser/themes/shared/syncedtabs/sidebar.inc.css b/browser/themes/shared/syncedtabs/sidebar.inc.css index 251096925800..dd184e0abeb9 100644 --- a/browser/themes/shared/syncedtabs/sidebar.inc.css +++ b/browser/themes/shared/syncedtabs/sidebar.inc.css @@ -232,10 +232,11 @@ body { .deck .syncIllustration, .deck .syncIllustrationIssue { - height: 91px; + height: 174px; margin: 38px 8px 15px; background-position: center; background-repeat: no-repeat; + background-size: contain; } .deck .syncIllustration { diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure index f54bed4bebf4..d78cf168260b 100755 --- a/build/moz.configure/toolchain.configure +++ b/build/moz.configure/toolchain.configure @@ -700,10 +700,10 @@ def toolchain_search_path_for(host_or_target): target: vc_compiler_path, }[host_or_target] - @depends(vc_path, original_path) + @depends(vc_path, original_path, developer_options) @imports('os') @imports(_from='os', _import='environ') - def toolchain_search_path(vc_compiler_path, original_path): + def toolchain_search_path(vc_compiler_path, original_path, developer_options): result = list(original_path) if vc_compiler_path: @@ -719,20 +719,24 @@ def toolchain_search_path_for(host_or_target): # `mach artifact toolchain` installs clang. mozbuild_state_dir = environ.get('MOZBUILD_STATE_PATH', os.path.expanduser(os.path.join('~', '.mozbuild'))) + bootstrapped = [] + bootstrap_clang_path = os.path.join(mozbuild_state_dir, 'clang', 'bin') - result.append(bootstrap_clang_path) + bootstrapped.append(bootstrap_clang_path) bootstrap_cbindgen_path = os.path.join(mozbuild_state_dir, 'cbindgen') - result.append(bootstrap_cbindgen_path) + bootstrapped.append(bootstrap_cbindgen_path) bootstrap_nasm_path = os.path.join(mozbuild_state_dir, 'nasm') - result.append(bootstrap_nasm_path) + bootstrapped.append(bootstrap_nasm_path) # Also add the rustup install directory for cargo/rustc. rustup_path = os.path.expanduser(os.path.join('~', '.cargo', 'bin')) result.append(rustup_path) - return result + if developer_options: + return bootstrapped + result + return result + bootstrapped return toolchain_search_path diff --git a/config/check_spidermonkey_style.py b/config/check_spidermonkey_style.py index 6f04fd30d675..5f785dfb8248 100644 --- a/config/check_spidermonkey_style.py +++ b/config/check_spidermonkey_style.py @@ -62,7 +62,7 @@ included_inclnames_to_ignore = set([ 'javascript-trace.h', # generated in $OBJDIR if HAVE_DTRACE is defined 'frontend/ReservedWordsGenerated.h', # generated in $OBJDIR 'gc/StatsPhasesGenerated.h', # generated in $OBJDIR - 'gc/StatsPhasesGenerated.cpp', # generated in $OBJDIR + 'gc/StatsPhasesGenerated.inc', # generated in $OBJDIR 'jit/LOpcodes.h', # generated in $OBJDIR 'jit/MOpcodes.h', # generated in $OBJDIR 'jscustomallocator.h', # provided by embedders; allowed to be missing @@ -118,7 +118,7 @@ oddly_ordered_inclnames = set([ # Included in the body of frontend/TokenStream.h 'frontend/ReservedWordsGenerated.h', 'gc/StatsPhasesGenerated.h', # Included in the body of gc/Statistics.h - 'gc/StatsPhasesGenerated.cpp', # Included in the body of gc/Statistics.cpp + 'gc/StatsPhasesGenerated.inc', # Included in the body of gc/Statistics.cpp 'psapi.h', # Must be included after "util/Windows.h" on Windows 'machine/endian.h', # Must be included after on BSD 'winbase.h', # Must precede other system headers(?) diff --git a/devtools/client/debugger/src/actions/sources/select.js b/devtools/client/debugger/src/actions/sources/select.js index 590955af5c29..8e4fd3339b85 100644 --- a/devtools/client/debugger/src/actions/sources/select.js +++ b/devtools/client/debugger/src/actions/sources/select.js @@ -84,7 +84,7 @@ export const clearSelectedLocation = (cx: Context) => ({ export function selectSourceURL( cx: Context, url: string, - options: PartialPosition = { line: 1 } + options: PartialPosition = {} ) { return async ({ dispatch, getState, sourceMaps }: ThunkArgs) => { const source = getSourceByURL(getState(), url); @@ -105,7 +105,7 @@ export function selectSourceURL( export function selectSource( cx: Context, sourceId: string, - options: PartialPosition = { line: 1 } + options: PartialPosition = {} ) { return async ({ dispatch }: ThunkArgs) => { const location = createLocation({ ...options, sourceId }); diff --git a/devtools/client/debugger/src/components/Editor/Preview/Popup.js b/devtools/client/debugger/src/components/Editor/Preview/Popup.js index 2913f3c11485..2560c699d224 100644 --- a/devtools/client/debugger/src/components/Editor/Preview/Popup.js +++ b/devtools/client/debugger/src/components/Editor/Preview/Popup.js @@ -67,12 +67,28 @@ export class Popup extends Component { componentDidMount() { this.startTimer(); + this.addHighlight(); } componentWillUnmount() { if (this.timerId) { clearInterval(this.timerId); } + this.removeHighlight(); + } + + addHighlight() { + const target = this.props.preview.target; + if (target) { + target.classList.add("preview-selection"); + } + } + + removeHighlight() { + const target = this.props.preview.target; + if (target) { + target.classList.remove("preview-selection"); + } } startTimer() { diff --git a/devtools/client/debugger/src/components/Editor/Preview/index.js b/devtools/client/debugger/src/components/Editor/Preview/index.js index 216ea4f7fb50..488f54b85be8 100644 --- a/devtools/client/debugger/src/components/Editor/Preview/index.js +++ b/devtools/client/debugger/src/components/Editor/Preview/index.js @@ -30,20 +30,6 @@ type State = { selecting: boolean, }; -function getElementFromPos(pos: DOMRect) { - // We need to use element*s*AtPoint because the tooltip overlays - // the token and thus an undesirable element may be returned - const elementsAtPoint = [ - // $FlowIgnore - ...document.elementsFromPoint( - pos.x + pos.width / 2, - pos.y + pos.height / 2 - ), - ]; - - return elementsAtPoint.find(el => el.className.startsWith("cm-")); -} - class Preview extends PureComponent { target = null; constructor(props) { @@ -65,10 +51,6 @@ class Preview extends PureComponent { codeMirrorWrapper.removeEventListener("mousedown", this.onMouseDown); } - componentDidUpdate(prevProps) { - this.updateHighlight(prevProps); - } - updateListeners(prevProps: ?Props) { const { codeMirror } = this.props.editor; const codeMirrorWrapper = codeMirror.getWrapperElement(); @@ -78,34 +60,14 @@ class Preview extends PureComponent { codeMirrorWrapper.addEventListener("mousedown", this.onMouseDown); } - updateHighlight(prevProps) { - const { preview } = this.props; - - if (preview && preview.target.matches(":hover")) { - const target = getElementFromPos(preview.cursorPos); - target && target.classList.add("preview-selection"); - } - - if (prevProps.preview && prevProps.preview !== preview) { - const target = getElementFromPos(prevProps.preview.cursorPos); - target && target.classList.remove("preview-selection"); - } - } - onTokenEnter = ({ target, tokenPos }) => { - const { cx, editor, updatePreview, preview } = this.props; + const { cx, editor, updatePreview } = this.props; - if (cx.isPaused && (!preview || target !== preview.target)) { + if (cx.isPaused && !this.state.selecting) { updatePreview(cx, target, tokenPos, editor.codeMirror); } }; - onScroll = () => { - if (this.props.cx.isPaused) { - this.props.clearPreview(this.props.cx); - } - }; - onMouseUp = () => { if (this.props.cx.isPaused) { this.setState({ selecting: false }); @@ -120,6 +82,12 @@ class Preview extends PureComponent { } }; + onScroll = () => { + if (this.props.cx.isPaused) { + this.props.clearPreview(this.props.cx); + } + }; + render() { const { preview } = this.props; if (!preview || this.state.selecting) { diff --git a/devtools/client/debugger/src/utils/location.js b/devtools/client/debugger/src/utils/location.js index 1124ea9c1bea..bcc1b7acb2ee 100644 --- a/devtools/client/debugger/src/utils/location.js +++ b/devtools/client/debugger/src/utils/location.js @@ -27,7 +27,8 @@ export function comparePosition(a: ?PartialPosition, b: ?PartialPosition) { export function createLocation({ sourceId, - line = 1, + // Line 0 represents no specific line chosen for action + line = 0, column, sourceUrl = "", }: IncompleteLocation): SourceLocation { diff --git a/devtools/client/debugger/test/mochitest/browser.ini b/devtools/client/debugger/test/mochitest/browser.ini index 8a18eccb2e2c..71d00fbacff1 100644 --- a/devtools/client/debugger/test/mochitest/browser.ini +++ b/devtools/client/debugger/test/mochitest/browser.ini @@ -664,6 +664,7 @@ support-files = examples/doc-worker-scopes.html examples/scopes-worker.js examples/doc-event-handler.html + examples/doc-editor-scroll.html examples/doc-eval-throw.html examples/doc-sourceURL-breakpoint.html examples/doc-step-in-uninitialized.html @@ -710,6 +711,7 @@ skip-if = (os == "win" && ccov) # Bug 1424154 [browser_dbg-debug-line.js] [browser_dbg-debugger-buttons.js] [browser_dbg-editor-gutter.js] +[browser_dbg-editor-scroll.js] [browser_dbg-editor-select.js] [browser_dbg-editor-highlight.js] [browser_dbg-ember-quickstart.js] diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-editor-scroll.js b/devtools/client/debugger/test/mochitest/browser_dbg-editor-scroll.js new file mode 100644 index 000000000000..708940b49c06 --- /dev/null +++ b/devtools/client/debugger/test/mochitest/browser_dbg-editor-scroll.js @@ -0,0 +1,46 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . */ + +// Tests that the editor keeps proper scroll position per document +// while also moving to the correct location upon pause/breakpoint selection +requestLongerTimeout(2); + +add_task(async function() { + // This test runs too slowly on linux debug. I'd like to figure out + // which is the slowest part of this and make it run faster, but to + // fix a frequent failure allow a longer timeout. + const dbg = await initDebugger("doc-editor-scroll.html"); + const simple1 = findSource(dbg, "simple1.js"); + + // Set the initial breakpoint. + await selectSource(dbg, "simple1"); + await addBreakpoint(dbg, simple1, 26); + + const cm = getCM(dbg); + + info("Open long file, scroll down to line below the fold"); + await selectSource(dbg, "long"); + cm.scrollTo(0, 600); + + info("Ensure vertical scroll is the same after switching documents"); + await selectSource(dbg, "simple1"); + is(cm.getScrollInfo().top, 0); + await selectSource(dbg, "long"); + is(cm.getScrollInfo().top, 600); + + info("Trigger a pause, click on a frame, ensure the right line is selected"); + invokeInTab("doNamedEval"); + await waitForPaused(dbg); + findElement(dbg, "frame", 1).focus(); + await clickElement(dbg, "frame", 1); + ok(cm.getScrollInfo().top != 0, "frame scrolled down to correct location"); + + info("Navigating while paused, goes to the correct location"); + await selectSource(dbg, "long"); + is(cm.getScrollInfo().top, 600); + + info("Open new source, ensure it's at 0 scroll"); + await selectSource(dbg, "frames"); + is(cm.getScrollInfo().top, 0); +}); diff --git a/devtools/client/debugger/test/mochitest/examples/doc-editor-scroll.html b/devtools/client/debugger/test/mochitest/examples/doc-editor-scroll.html new file mode 100644 index 000000000000..e2992988e67d --- /dev/null +++ b/devtools/client/debugger/test/mochitest/examples/doc-editor-scroll.html @@ -0,0 +1,17 @@ + + + + + + Debugger test page + + + + + + + + + diff --git a/devtools/server/actors/breakpoint.js b/devtools/server/actors/breakpoint.js index d25d6aef3fb5..4869a708b8aa 100644 --- a/devtools/server/actors/breakpoint.js +++ b/devtools/server/actors/breakpoint.js @@ -172,15 +172,15 @@ BreakpointActor.prototype = { hit: function(frame) { // Don't pause if we are currently stepping (in or over) or the frame is // black-boxed. + const location = this.threadActor.sources.getFrameLocation(frame); const { sourceActor, line, column, - } = this.threadActor.sources.getFrameLocation(frame); - const url = sourceActor.url; + } = location; if ( - this.threadActor.sources.isBlackBoxed(url, line, column) || + this.threadActor.sources.isBlackBoxed(sourceActor.url, line, column) || this.threadActor.skipBreakpoints || frame.onStep ) { @@ -198,6 +198,10 @@ BreakpointActor.prototype = { return undefined; } + if (!this.threadActor.hasMoved(location, "breakpoint")) { + return undefined; + } + const reason = { type: "breakpoint", actors: [this.actorID] }; const { condition, logValue } = this.options || {}; @@ -238,7 +242,7 @@ BreakpointActor.prototype = { } const message = { - filename: url, + filename: sourceActor.url, lineNumber: line, columnNumber: column, level: "logPoint", diff --git a/devtools/server/actors/thread.js b/devtools/server/actors/thread.js index bdea537e3045..b9b252b3885b 100644 --- a/devtools/server/actors/thread.js +++ b/devtools/server/actors/thread.js @@ -63,6 +63,8 @@ const ThreadActor = ActorClassWithSpec(threadSpec, { this._observingNetwork = false; this._eventBreakpoints = []; + this._priorPause = null; + this._options = { autoBlackBox: false, }; @@ -535,6 +537,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, { }; const pkt = onPacket(packet); + this._priorPause = pkt; this.conn.send(pkt); } catch (error) { reportError(error); @@ -656,6 +659,26 @@ const ThreadActor = ActorClassWithSpec(threadSpec, { return result; }, + hasMoved: function(newLocation, newType) { + if (!this._priorPause) { + return true; + } + + // Recursion/Loops makes it okay to resume and land at + // the same breakpoint or debugger statement. + // It is not okay to transition from a breakpoint to debugger statement + // or a step to a debugger statement. + const { type } = this._priorPause.why; + + if (type == newType) { + return true; + } + + const { line, column } = this._priorPause.frame.where; + return line !== newLocation.line + || column !== newLocation.column; + }, + // Return whether reaching a script offset should be considered a distinct // "step" from another location. _intraFrameLocationIsStepTarget: function(startLocation, script, offset) { @@ -673,10 +696,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, { // TODO(logan): When we remove points points, this can be removed too as // we assert that we're at a different frame offset from the last time // we paused. - const lineChanged = startLocation.line !== location.line; - const columnChanged = - startLocation.column !== location.column; - if (!lineChanged && !columnChanged) { + if (!this.hasMoved(location)) { return false; } @@ -1478,12 +1498,16 @@ const ThreadActor = ActorClassWithSpec(threadSpec, { * The stack frame that contained the debugger statement. */ onDebuggerStatement: function(frame) { - // Don't pause if we are currently stepping (in or over) or the frame is - // black-boxed. - const { sourceActor } = this.sources.getFrameLocation(frame); - const url = sourceActor ? sourceActor.url : null; + const location = this.sources.getFrameLocation(frame); + const url = location.sourceActor.url; - if (this.skipBreakpoints || this.sources.isBlackBoxed(url) || frame.onStep) { + // Don't pause if + // 1. the debugger is in the same position + // 2. breakpoints are disabled + // 3. the source is blackboxed + if (!this.hasMoved(location, "debuggerStatement") + || this.skipBreakpoints + || this.sources.isBlackBoxed(url)) { return undefined; } diff --git a/devtools/server/tests/unit/test_blackboxing-01.js b/devtools/server/tests/unit/test_blackboxing-01.js index bbc6052eec53..ed4c991ef382 100644 --- a/devtools/server/tests/unit/test_blackboxing-01.js +++ b/devtools/server/tests/unit/test_blackboxing-01.js @@ -123,11 +123,12 @@ function evalCode() { "" + function runTest() { // line 1 doStuff( // line 2 - Break here function (n) { // line 3 - Step through `doStuff` to here - debugger; // line 4 - } // line 5 - ); // line 6 - } + "\n" // line 7 - + "debugger;", // line 8 + (() => {})(); // line 4 + debugger; // line 5 + } // line 6 + ); // line 7 + } + "\n" // line 8 + + "debugger;", // line 9 gDebuggee, "1.8", SOURCE_URL, diff --git a/devtools/server/tests/unit/test_breakpoint-24.js b/devtools/server/tests/unit/test_breakpoint-24.js new file mode 100644 index 000000000000..a238443ad277 --- /dev/null +++ b/devtools/server/tests/unit/test_breakpoint-24.js @@ -0,0 +1,181 @@ +/* eslint-disable max-nested-callbacks */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Bug 1441183 - Verify that the debugger advances to a new location + * when encountering debugger statements and brakpoints + */ +add_task(threadClientTest(async props => { + await testDebuggerStatements(props); + await testBreakpoints(props); + await testBreakpointsAndDebuggerStatements(props); + await testLoops(props); +})); + +// Ensure that we advance to the next line when we +// step to a debugger statement and resume. +async function testDebuggerStatements({threadClient, targetFront}) { + const consoleFront = await targetFront.getFront("console"); + consoleFront.evaluateJSAsync( + `function foo(stop) { + debugger; + debugger; + debugger; + } + foo(); + //# sourceURL=http://example.com/code.js` + ); + + await performActions(threadClient, [ + [ + "paused at first debugger statement", + {line: 2, type: "debuggerStatement"}, + "stepOver", + ], + [ + "paused at the second debugger statement", + {line: 3, type: "resumeLimit"}, + "resume", + ], + [ + "paused at the third debugger statement", + {line: 4, type: "debuggerStatement"}, + "resume", + ], + ]); +} + +// Ensure that we advance to the next line when we hit a breakpoint +// on a line with a debugger statement and resume. +async function testBreakpointsAndDebuggerStatements({threadClient, targetFront}) { + const consoleFront = await targetFront.getFront("console"); + consoleFront.evaluateJSAsync( + `function foo(stop) { + debugger; + debugger; + debugger; + } + foo(); + //# sourceURL=http://example.com/testBreakpointsAndDebuggerStatements.js` + ); + + threadClient.setBreakpoint( + { sourceUrl: "http://example.com/testBreakpointsAndDebuggerStatements.js", line: 3 }, + {} + ); + + await performActions(threadClient, [ + [ + "paused at first debugger statement", + {line: 2, type: "debuggerStatement"}, + "resume", + ], + [ + "paused at the breakpoint at the second debugger statement", + {line: 3, type: "breakpoint"}, + "resume", + ], + [ + "pause at the third debugger statement", + {line: 4, type: "debuggerStatement"}, + "resume", + ], + ]); +} + +// Ensure that we advance to the next line when we step to +// a line with a breakpoint and resume. +async function testBreakpoints({threadClient, targetFront}) { + const consoleFront = await targetFront.getFront("console"); + consoleFront.evaluateJSAsync( + `function foo(stop) { + debugger; + a(); + debugger; + } + function a() {} + foo(); + //# sourceURL=http://example.com/testBreakpoints.js` + ); + + threadClient.setBreakpoint( + { sourceUrl: "http://example.com/testBreakpoints.js", line: 3 }, + {} + ); + + await performActions(threadClient, [ + [ + "paused at first debugger statement", + {line: 2, type: "debuggerStatement"}, + "stepOver", + ], + [ + "paused at a()", + {line: 3, type: "resumeLimit"}, + "resume", + ], + [ + "pause at the second debugger satement", + {line: 4, type: "debuggerStatement"}, + "resume", + ], + ]); +} + +// Ensure that we advance to the next line when we step to +// a line with a breakpoint and resume. +async function testLoops({threadClient, targetFront}) { + const consoleFront = await targetFront.getFront("console"); + consoleFront.evaluateJSAsync( + `function foo(stop) { + let i = 0; + debugger; + while (i++ < 2) { + debugger; + } + debugger; + } + foo(); + //# sourceURL=http://example.com/testLoops.js` + ); + + await performActions(threadClient, [ + [ + "paused at first debugger statement", + {line: 3, type: "debuggerStatement"}, + "resume", + ], + [ + "pause at the second debugger satement", + {line: 5, type: "debuggerStatement"}, + "resume", + ], + [ + "pause at the second debugger satement (2nd time)", + {line: 5, type: "debuggerStatement"}, + "resume", + ], + [ + "pause at the third debugger satement", + {line: 7, type: "debuggerStatement"}, + "resume", + ], + ]); +} + +async function performActions(threadClient, actions) { + for (const action of actions) { + await performAction(threadClient, action); + } +} + +async function performAction(threadClient, [description, result, action]) { + info(description); + const packet = await waitForEvent(threadClient, "paused"); + Assert.equal(packet.frame.where.line, result.line); + Assert.equal(packet.why.type, result.type); + await threadClient[action](); +} diff --git a/devtools/server/tests/unit/xpcshell.ini b/devtools/server/tests/unit/xpcshell.ini index a1f24b7a6f14..711015c3c976 100644 --- a/devtools/server/tests/unit/xpcshell.ini +++ b/devtools/server/tests/unit/xpcshell.ini @@ -133,6 +133,7 @@ reason = bug 1104838 [test_breakpoint-22.js] skip-if = true # breakpoint sliding is not supported bug 1525685 [test_breakpoint-23.js] +[test_breakpoint-24.js] [test_conditional_breakpoint-01.js] [test_conditional_breakpoint-02.js] [test_conditional_breakpoint-03.js] diff --git a/devtools/shared/css/generated/properties-db.js b/devtools/shared/css/generated/properties-db.js index 02e5d9f23c8d..c1ac390ecd4f 100644 --- a/devtools/shared/css/generated/properties-db.js +++ b/devtools/shared/css/generated/properties-db.js @@ -10812,18 +10812,6 @@ exports.PREFERENCES = [ "scroll-padding-top", "layout.css.scroll-snap-v1.enabled" ], - [ - "-webkit-text-stroke-width", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-text-fill-color", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-text-stroke-color", - "layout.css.prefixes.webkit" - ], [ "overflow-clip-box", "layout.css.overflow-clip-box.enabled" @@ -10832,10 +10820,6 @@ exports.PREFERENCES = [ "overscroll-behavior", "layout.css.overscroll-behavior.enabled" ], - [ - "-webkit-text-stroke", - "layout.css.prefixes.webkit" - ], [ "scroll-margin", "layout.css.scroll-snap-v1.enabled" @@ -10860,178 +10844,78 @@ exports.PREFERENCES = [ "scroll-padding-inline", "layout.css.scroll-snap-v1.enabled" ], - [ - "-webkit-background-clip", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-background-origin", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-background-size", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-border-top-left-radius", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-border-top-right-radius", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-border-bottom-right-radius", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-border-bottom-left-radius", - "layout.css.prefixes.webkit" - ], [ "-moz-transition-duration", "layout.css.prefixes.transitions" ], - [ - "-webkit-transition-duration", - "layout.css.prefixes.webkit" - ], [ "-moz-transition-timing-function", "layout.css.prefixes.transitions" ], - [ - "-webkit-transition-timing-function", - "layout.css.prefixes.webkit" - ], [ "-moz-transition-property", "layout.css.prefixes.transitions" ], - [ - "-webkit-transition-property", - "layout.css.prefixes.webkit" - ], [ "-moz-transition-delay", "layout.css.prefixes.transitions" ], - [ - "-webkit-transition-delay", - "layout.css.prefixes.webkit" - ], [ "-moz-animation-name", "layout.css.prefixes.animations" ], - [ - "-webkit-animation-name", - "layout.css.prefixes.webkit" - ], [ "-moz-animation-duration", "layout.css.prefixes.animations" ], - [ - "-webkit-animation-duration", - "layout.css.prefixes.webkit" - ], [ "-moz-animation-timing-function", "layout.css.prefixes.animations" ], - [ - "-webkit-animation-timing-function", - "layout.css.prefixes.webkit" - ], [ "-moz-animation-iteration-count", "layout.css.prefixes.animations" ], - [ - "-webkit-animation-iteration-count", - "layout.css.prefixes.webkit" - ], [ "-moz-animation-direction", "layout.css.prefixes.animations" ], - [ - "-webkit-animation-direction", - "layout.css.prefixes.webkit" - ], [ "-moz-animation-play-state", "layout.css.prefixes.animations" ], - [ - "-webkit-animation-play-state", - "layout.css.prefixes.webkit" - ], [ "-moz-animation-fill-mode", "layout.css.prefixes.animations" ], - [ - "-webkit-animation-fill-mode", - "layout.css.prefixes.webkit" - ], [ "-moz-animation-delay", "layout.css.prefixes.animations" ], - [ - "-webkit-animation-delay", - "layout.css.prefixes.webkit" - ], [ "-moz-transform", "layout.css.prefixes.transforms" ], - [ - "-webkit-transform", - "layout.css.prefixes.webkit" - ], [ "-moz-perspective", "layout.css.prefixes.transforms" ], - [ - "-webkit-perspective", - "layout.css.prefixes.webkit" - ], [ "-moz-perspective-origin", "layout.css.prefixes.transforms" ], - [ - "-webkit-perspective-origin", - "layout.css.prefixes.webkit" - ], [ "-moz-backface-visibility", "layout.css.prefixes.transforms" ], - [ - "-webkit-backface-visibility", - "layout.css.prefixes.webkit" - ], [ "-moz-transform-style", "layout.css.prefixes.transforms" ], - [ - "-webkit-transform-style", - "layout.css.prefixes.webkit" - ], [ "-moz-transform-origin", "layout.css.prefixes.transforms" ], - [ - "-webkit-transform-origin", - "layout.css.prefixes.webkit" - ], [ "-webkit-appearance", "layout.css.webkit-appearance.enabled" @@ -11040,14 +10924,6 @@ exports.PREFERENCES = [ "-moz-column-span", "layout.css.column-span.enabled" ], - [ - "-webkit-box-shadow", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-filter", - "layout.css.prefixes.webkit" - ], [ "-moz-font-feature-settings", "layout.css.prefixes.font-features" @@ -11056,10 +10932,6 @@ exports.PREFERENCES = [ "-moz-font-language-override", "layout.css.prefixes.font-features" ], - [ - "-webkit-text-size-adjust", - "layout.css.prefixes.webkit" - ], [ "offset-block-start", "layout.css.offset-logical-properties.enabled" @@ -11076,156 +10948,20 @@ exports.PREFERENCES = [ "offset-inline-end", "layout.css.offset-logical-properties.enabled" ], - [ - "-webkit-flex-direction", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-flex-wrap", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-justify-content", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-align-content", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-align-items", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-flex-grow", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-flex-shrink", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-align-self", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-order", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-flex-basis", - "layout.css.prefixes.webkit" - ], [ "-moz-box-sizing", "layout.css.prefixes.box-sizing" ], - [ - "-webkit-box-sizing", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-user-select", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask-repeat", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask-position-x", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask-position-y", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask-clip", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask-origin", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask-size", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask-composite", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask-image", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-box-align", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-box-direction", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-box-flex", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-box-orient", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-box-pack", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-box-ordinal-group", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-border-radius", - "layout.css.prefixes.webkit" - ], [ "-moz-border-image", "layout.css.prefixes.border-image" ], - [ - "-webkit-border-image", - "layout.css.prefixes.webkit" - ], [ "-moz-transition", "layout.css.prefixes.transitions" ], - [ - "-webkit-transition", - "layout.css.prefixes.webkit" - ], [ "-moz-animation", "layout.css.prefixes.animations" - ], - [ - "-webkit-animation", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-flex-flow", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-flex", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask", - "layout.css.prefixes.webkit" - ], - [ - "-webkit-mask-position", - "layout.css.prefixes.webkit" ] ]; diff --git a/dom/animation/test/mozilla/test_disabled_properties.html b/dom/animation/test/mozilla/test_disabled_properties.html index 9e264821121d..985657aa26e0 100644 --- a/dom/animation/test/mozilla/test_disabled_properties.html +++ b/dom/animation/test/mozilla/test_disabled_properties.html @@ -13,20 +13,20 @@ function waitForSetPref(pref, value) { } /* - * These tests rely on the fact that the -webkit-text-fill-color property - * is disabled by the layout.css.prefixes.webkit pref. If we ever remove that - * pref we will need to substitute some other pref:property combination. + * These tests rely on the fact that the -webkit-line-clamp property is + * disabled by the layout.css.webkit-line-clamp.enabled pref. If we ever remove + * that pref we will need to substitute some other pref:property combination. */ promise_test(function(t) { - return waitForSetPref('layout.css.prefixes.webkit', true).then(() => { - var anim = addDiv(t).animate({ webkitTextFillColor: [ 'green', 'blue' ]}); + return waitForSetPref('layout.css.webkit-line-clamp.enabled', true).then(() => { + var anim = addDiv(t).animate({ webkitLineClamp: [ '2', '4' ]}); assert_equals(anim.effect.getKeyframes().length, 2, 'A property-indexed keyframe specifying only enabled' + ' properties produces keyframes'); - return waitForSetPref('layout.css.prefixes.webkit', false); + return waitForSetPref('layout.css.webkit-line-clamp.enabled', false); }).then(() => { - var anim = addDiv(t).animate({ webkitTextFillColor: [ 'green', 'blue' ]}); + var anim = addDiv(t).animate({ webkitLineClamp: [ '2', '4' ]}); assert_equals(anim.effect.getKeyframes().length, 0, 'A property-indexed keyframe specifying only disabled' + ' properties produces no keyframes'); @@ -35,8 +35,8 @@ promise_test(function(t) { promise_test(function(t) { var createAnim = () => { - var anim = addDiv(t).animate([ { webkitTextFillColor: 'green' }, - { webkitTextFillColor: 'blue' } ]); + var anim = addDiv(t).animate([ { webkitLineClamp: '2' }, + { webkitLineClamp: '4' } ]); assert_equals(anim.effect.getKeyframes().length, 2, 'Animation specified using a keyframe sequence should' + ' return the same number of keyframes regardless of' @@ -55,17 +55,17 @@ promise_test(function(t) { `${descr} should NOT have the '${property}' property`); }; - return waitForSetPref('layout.css.prefixes.webkit', true).then(() => { + return waitForSetPref('layout.css.webkit-line-clamp.enabled', true).then(() => { var anim = createAnim(); - assert_has_property(anim, 0, 'Initial keyframe', 'webkitTextFillColor'); - assert_has_property(anim, 1, 'Final keyframe', 'webkitTextFillColor'); - return waitForSetPref('layout.css.prefixes.webkit', false); + assert_has_property(anim, 0, 'Initial keyframe', 'webkitLineClamp'); + assert_has_property(anim, 1, 'Final keyframe', 'webkitLineClamp'); + return waitForSetPref('layout.css.webkit-line-clamp.enabled', false); }).then(() => { var anim = createAnim(); assert_does_not_have_property(anim, 0, 'Initial keyframe', - 'webkitTextFillColor'); + 'webkitLineClamp'); assert_does_not_have_property(anim, 1, 'Final keyframe', - 'webkitTextFillColor'); + 'webkitLineClamp'); }); }, 'Specifying a disabled property using a keyframe sequence'); diff --git a/dom/animation/test/mozilla/test_discrete_animations.html b/dom/animation/test/mozilla/test_discrete_animations.html index bc27b6d07fb7..d4826a74bd5b 100644 --- a/dom/animation/test/mozilla/test_discrete_animations.html +++ b/dom/animation/test/mozilla/test_discrete_animations.html @@ -9,7 +9,6 @@ setup({explicit_done: true}); SpecialPowers.pushPrefEnv( { "set": [ ["layout.css.osx-font-smoothing.enabled", true], - ["layout.css.prefixes.webkit", true] ] }, function() { window.open("file_discrete_animations.html"); diff --git a/dom/base/WebKitCSSMatrix.cpp b/dom/base/WebKitCSSMatrix.cpp index fb3207d3bb93..1b75fb2ac98d 100644 --- a/dom/base/WebKitCSSMatrix.cpp +++ b/dom/base/WebKitCSSMatrix.cpp @@ -18,8 +18,7 @@ namespace dom { static const double sRadPerDegree = 2.0 * M_PI / 360.0; bool WebKitCSSMatrix::FeatureEnabled(JSContext* aCx, JSObject* aObj) { - return StaticPrefs::layout_css_DOMMatrix_enabled() && - StaticPrefs::layout_css_prefixes_webkit(); + return StaticPrefs::layout_css_DOMMatrix_enabled(); } already_AddRefed WebKitCSSMatrix::Constructor( diff --git a/dom/base/nsGlobalWindowInner.cpp b/dom/base/nsGlobalWindowInner.cpp index de10a5ecff6c..9ea84587c1a7 100644 --- a/dom/base/nsGlobalWindowInner.cpp +++ b/dom/base/nsGlobalWindowInner.cpp @@ -4479,13 +4479,15 @@ Storage* nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError) { } // Note that this behavior is observable: if we grant storage permission to a - // tracker, we pass from the partitioned LocalStorage to the 'normal' - // LocalStorage. The previous data is lost and the 2 window.localStorage - // objects, before and after the permission granted, will be different. + // tracker, we pass from the partitioned LocalStorage (or a partitioned cookie + // jar) to the 'normal' one. The previous data is lost and the 2 + // window.localStorage objects, before and after the permission granted, will + // be different. if ((StoragePartitioningEnabled(access, cookieSettings) || !ShouldPartitionStorage(access)) && (!mLocalStorage || - mLocalStorage->Type() == Storage::ePartitionedLocalStorage)) { + mLocalStorage->Type() == Storage::ePartitionedLocalStorage || + mLocalStorage->StoragePrincipal() != GetEffectiveStoragePrincipal())) { RefPtr storage; if (NextGenLocalStorageEnabled()) { @@ -6963,8 +6965,7 @@ void nsGlobalWindowInner::StorageAccessGranted() { // If we have a partitioned localStorage, it's time to replace it with a real // one in order to receive notifications. - if (mLocalStorage && - mLocalStorage->Type() == Storage::ePartitionedLocalStorage) { + if (mLocalStorage) { IgnoredErrorResult error; GetLocalStorage(error); if (NS_WARN_IF(error.Failed())) { diff --git a/dom/canvas/test/webgl-mochitest/mochitest.ini b/dom/canvas/test/webgl-mochitest/mochitest.ini index 61e5db7e469f..738e86540fe2 100644 --- a/dom/canvas/test/webgl-mochitest/mochitest.ini +++ b/dom/canvas/test/webgl-mochitest/mochitest.ini @@ -118,6 +118,5 @@ skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests [test_video_fastpath_vp9.html] [test_webglcontextcreationerror.html] [test_webgl_fingerprinting_resistance.html] -fail-if = (os == 'mac') # on try server, LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE = 512 on mac [test_without_index_validation.html] [test_vertexattrib4f_update.html] diff --git a/dom/chrome-webidl/JSWindowActor.webidl b/dom/chrome-webidl/JSWindowActor.webidl index d6683a573cda..7ec246d61829 100644 --- a/dom/chrome-webidl/JSWindowActor.webidl +++ b/dom/chrome-webidl/JSWindowActor.webidl @@ -22,6 +22,9 @@ interface JSWindowActor { [ChromeOnly, ChromeConstructor] interface JSWindowActorParent { readonly attribute WindowGlobalParent manager; + + [Throws] + readonly attribute CanonicalBrowsingContext? browsingContext; }; JSWindowActorParent implements JSWindowActor; diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index 0a9a90151ebf..de5063ab8df8 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -19,7 +19,6 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/Preferences.h" #include "mozilla/PresShell.h" -#include "mozilla/StaticPrefs.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/Event.h" @@ -1035,24 +1034,18 @@ nsresult EventListenerManager::HandleEventSubType(Listener* aListener, EventMessage EventListenerManager::GetLegacyEventMessage( EventMessage aEventMessage) const { - // (If we're off-main-thread, we can't check the pref; so we just behave as - // if it's disabled.) - if (mIsMainThreadELM) { - if (StaticPrefs::layout_css_prefixes_webkit()) { - // webkit-prefixed legacy events: - if (aEventMessage == eTransitionEnd) { - return eWebkitTransitionEnd; - } - if (aEventMessage == eAnimationStart) { - return eWebkitAnimationStart; - } - if (aEventMessage == eAnimationEnd) { - return eWebkitAnimationEnd; - } - if (aEventMessage == eAnimationIteration) { - return eWebkitAnimationIteration; - } - } + // webkit-prefixed legacy events: + if (aEventMessage == eTransitionEnd) { + return eWebkitTransitionEnd; + } + if (aEventMessage == eAnimationStart) { + return eWebkitAnimationStart; + } + if (aEventMessage == eAnimationEnd) { + return eWebkitAnimationEnd; + } + if (aEventMessage == eAnimationIteration) { + return eWebkitAnimationIteration; } switch (aEventMessage) { diff --git a/dom/ipc/JSWindowActorParent.cpp b/dom/ipc/JSWindowActorParent.cpp index 279a449ec99c..d9fb3ac892ce 100644 --- a/dom/ipc/JSWindowActorParent.cpp +++ b/dom/ipc/JSWindowActorParent.cpp @@ -87,6 +87,16 @@ void JSWindowActorParent::SendRawMessage(const JSWindowActorMessageMeta& aMeta, } } +CanonicalBrowsingContext* JSWindowActorParent::GetBrowsingContext( + ErrorResult& aRv) { + if (!mManager) { + aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return nullptr; + } + + return mManager->BrowsingContext(); +} + void JSWindowActorParent::StartDestroy() { JSWindowActor::StartDestroy(); mCanSend = false; diff --git a/dom/ipc/JSWindowActorParent.h b/dom/ipc/JSWindowActorParent.h index 4dd901035dff..93e919d4a610 100644 --- a/dom/ipc/JSWindowActorParent.h +++ b/dom/ipc/JSWindowActorParent.h @@ -44,6 +44,7 @@ class JSWindowActorParent final : public JSWindowActor { void Init(const nsAString& aName, WindowGlobalParent* aManager); void StartDestroy(); void AfterDestroy(); + CanonicalBrowsingContext* GetBrowsingContext(ErrorResult& aRv); protected: void SendRawMessage(const JSWindowActorMessageMeta& aMeta, diff --git a/editor/composer/ComposerCommandsUpdater.cpp b/editor/composer/ComposerCommandsUpdater.cpp index 6d1189295301..2a67f329cb9b 100644 --- a/editor/composer/ComposerCommandsUpdater.cpp +++ b/editor/composer/ComposerCommandsUpdater.cpp @@ -199,13 +199,9 @@ ComposerCommandsUpdater::DidMerge(nsITransactionManager* aManager, # pragma mark - #endif -nsresult ComposerCommandsUpdater::Init(nsPIDOMWindowOuter* aDOMWindow) { - if (NS_WARN_IF(!aDOMWindow)) { - return NS_ERROR_INVALID_ARG; - } - mDOMWindow = aDOMWindow; - mDocShell = aDOMWindow->GetDocShell(); - return NS_OK; +void ComposerCommandsUpdater::Init(nsPIDOMWindowOuter& aDOMWindow) { + mDOMWindow = &aDOMWindow; + mDocShell = aDOMWindow.GetDocShell(); } nsresult ComposerCommandsUpdater::PrimeUpdateTimer() { diff --git a/editor/composer/ComposerCommandsUpdater.h b/editor/composer/ComposerCommandsUpdater.h index 6ba54a460f7c..eaecb0f1b2ed 100644 --- a/editor/composer/ComposerCommandsUpdater.h +++ b/editor/composer/ComposerCommandsUpdater.h @@ -48,7 +48,7 @@ class ComposerCommandsUpdater final : public nsIDocumentStateListener, // nsITransactionListener NS_DECL_NSITRANSACTIONLISTENER - nsresult Init(nsPIDOMWindowOuter* aDOMWindow); + void Init(nsPIDOMWindowOuter& aDOMWindow); /** * OnSelectionChange() is called when selection is changed in the editor. diff --git a/editor/composer/nsEditingSession.cpp b/editor/composer/nsEditingSession.cpp index aeed721ea5ea..43897c8f31e8 100644 --- a/editor/composer/nsEditingSession.cpp +++ b/editor/composer/nsEditingSession.cpp @@ -163,7 +163,7 @@ nsEditingSession::MakeWindowEditable(mozIDOMWindowProxy* aWindow, // aDoAfterUriLoad can be false only when making an existing window editable if (!aDoAfterUriLoad) { - rv = SetupEditorOnWindow(aWindow); + rv = SetupEditorOnWindow(MOZ_KnownLive(*window)); // mEditorStatus is set to the error reason // Since this is used only when editing an existing page, @@ -266,21 +266,9 @@ bool IsSupportedTextType(const char* aMIMEType) { return false; } -/*--------------------------------------------------------------------------- - - SetupEditorOnWindow - - nsIEditor setupEditorOnWindow (in nsIDOMWindow aWindow); -----------------------------------------------------------------------------*/ -NS_IMETHODIMP -nsEditingSession::SetupEditorOnWindow(mozIDOMWindowProxy* aWindow) { +nsresult nsEditingSession::SetupEditorOnWindow(nsPIDOMWindowOuter& aWindow) { mDoneSetup = true; - NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE); - auto* window = nsPIDOMWindowOuter::From(aWindow); - - nsresult rv; - // MIME CHECKING // must get the content type // Note: the doc gets this from the network channel during StartPageLoad, @@ -288,7 +276,7 @@ nsEditingSession::SetupEditorOnWindow(mozIDOMWindowProxy* aWindow) { nsAutoCString mimeCType; // then lets check the mime type - if (RefPtr doc = window->GetDoc()) { + if (RefPtr doc = aWindow.GetDoc()) { nsAutoString mimeType; doc->GetContentType(mimeType); AppendUTF16toUTF8(mimeType, mimeCType); @@ -348,8 +336,7 @@ nsEditingSession::SetupEditorOnWindow(mozIDOMWindowProxy* aWindow) { // now init the state maintainer // This allows notification of error state // even if we don't create an editor - rv = mComposerCommandsUpdater->Init(window); - NS_ENSURE_SUCCESS(rv, rv); + mComposerCommandsUpdater->Init(aWindow); if (mEditorStatus != eEditorCreationInProgress) { RefPtr updater = mComposerCommandsUpdater; @@ -366,7 +353,7 @@ nsEditingSession::SetupEditorOnWindow(mozIDOMWindowProxy* aWindow) { // Create editor and do other things // only if we haven't found some error above, - nsCOMPtr docShell = window->GetDocShell(); + nsCOMPtr docShell = aWindow.GetDocShell(); NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); RefPtr presShell = docShell->GetPresShell(); if (NS_WARN_IF(!presShell)) { @@ -401,14 +388,14 @@ nsEditingSession::SetupEditorOnWindow(mozIDOMWindowProxy* aWindow) { do_GetWeakReference(static_cast(htmlEditor.get())); } // set the editor on the docShell. The docShell now owns it. - rv = docShell->SetHTMLEditor(htmlEditor); + nsresult rv = docShell->SetHTMLEditor(htmlEditor); NS_ENSURE_SUCCESS(rv, rv); // setup the HTML editor command controller if (needHTMLController) { // The third controller takes an nsIEditor as the context rv = SetupEditorCommandController( - nsBaseCommandController::CreateHTMLEditorController, aWindow, + nsBaseCommandController::CreateHTMLEditorController, &aWindow, static_cast(htmlEditor), &mHTMLCommandControllerId); NS_ENSURE_SUCCESS(rv, rv); } @@ -523,7 +510,7 @@ nsEditingSession::TearDownEditorOnWindow(mozIDOMWindowProxy* aWindow) { if (mComposerCommandsUpdater && htmlEditor) { // Null out the editor on the controllers first to prevent their weak // references from pointing to a destroyed editor. - SetEditorOnControllers(aWindow, nullptr); + SetEditorOnControllers(*window, nullptr); } // Null out the editor on the docShell to trigger PreDestroy which @@ -879,7 +866,8 @@ nsresult nsEditingSession::EndDocumentLoad(nsIWebProgress* aWebProgress, mEditorStatus = eEditorErrorFileNotFound; } - nsIDocShell* docShell = nsPIDOMWindowOuter::From(domWindow)->GetDocShell(); + auto* window = nsPIDOMWindowOuter::From(domWindow); + nsIDocShell* docShell = window->GetDocShell(); NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); // better error handling? // cancel refresh from meta tags @@ -910,7 +898,7 @@ nsresult nsEditingSession::EndDocumentLoad(nsIWebProgress* aWebProgress, if (needsSetup) { mCanCreateEditor = false; - rv = SetupEditorOnWindow(domWindow); + rv = SetupEditorOnWindow(MOZ_KnownLive(*window)); if (NS_FAILED(rv)) { // If we had an error, setup timer to load a blank page later if (mLoadBlankDocTimer) { @@ -1087,24 +1075,13 @@ nsresult nsEditingSession::SetupEditorCommandController( return SetContextOnControllerById(controllers, aContext, *aControllerId); } -/*--------------------------------------------------------------------------- - - SetEditorOnControllers - - Set the editor on the controller(s) for this window -----------------------------------------------------------------------------*/ -NS_IMETHODIMP -nsEditingSession::SetEditorOnControllers(mozIDOMWindowProxy* aWindow, - nsIEditor* aEditor) { - NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER); - - auto* piWindow = nsPIDOMWindowOuter::From(aWindow); - +nsresult nsEditingSession::SetEditorOnControllers(nsPIDOMWindowOuter& aWindow, + HTMLEditor* aEditor) { nsCOMPtr controllers; - nsresult rv = piWindow->GetControllers(getter_AddRefs(controllers)); + nsresult rv = aWindow.GetControllers(getter_AddRefs(controllers)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr editorAsISupports = static_cast(aEditor); + nsCOMPtr editorAsISupports = static_cast(aEditor); if (mBaseCommandControllerId) { rv = SetContextOnControllerById(controllers, editorAsISupports, mBaseCommandControllerId); @@ -1209,7 +1186,7 @@ void nsEditingSession::RestoreAnimationMode(nsPIDOMWindowOuter* aWindow) { presContext->SetImageAnimationMode(mImageAnimationMode); } -nsresult nsEditingSession::DetachFromWindow(mozIDOMWindowProxy* aWindow) { +nsresult nsEditingSession::DetachFromWindow(nsPIDOMWindowOuter* aWindow) { NS_ENSURE_TRUE(mDoneSetup, NS_OK); NS_ASSERTION(mComposerCommandsUpdater, @@ -1221,14 +1198,12 @@ nsresult nsEditingSession::DetachFromWindow(mozIDOMWindowProxy* aWindow) { mLoadBlankDocTimer = nullptr; } - auto* window = nsPIDOMWindowOuter::From(aWindow); - // Remove controllers, webprogress listener, and otherwise // make things the way they were before we started editing. - RemoveEditorControllers(window); - RemoveWebProgressListener(window); - RestoreJSAndPlugins(window); - RestoreAnimationMode(window); + RemoveEditorControllers(aWindow); + RemoveWebProgressListener(aWindow); + RestoreJSAndPlugins(aWindow); + RestoreAnimationMode(aWindow); // Kill our weak reference to our original window, in case // it changes on restore, or otherwise dies. @@ -1237,7 +1212,7 @@ nsresult nsEditingSession::DetachFromWindow(mozIDOMWindowProxy* aWindow) { return NS_OK; } -nsresult nsEditingSession::ReattachToWindow(mozIDOMWindowProxy* aWindow) { +nsresult nsEditingSession::ReattachToWindow(nsPIDOMWindowOuter* aWindow) { NS_ENSURE_TRUE(mDoneSetup, NS_OK); NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE); @@ -1248,8 +1223,7 @@ nsresult nsEditingSession::ReattachToWindow(mozIDOMWindowProxy* aWindow) { // old editor ot the window. nsresult rv; - auto* window = nsPIDOMWindowOuter::From(aWindow); - nsIDocShell* docShell = window->GetDocShell(); + nsIDocShell* docShell = aWindow->GetDocShell(); NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); mDocShell = do_GetWeakReference(docShell); @@ -1263,7 +1237,7 @@ nsresult nsEditingSession::ReattachToWindow(mozIDOMWindowProxy* aWindow) { mEditorStatus = eEditorCreationInProgress; // Adds back web progress listener. - rv = PrepareForEditing(window); + rv = PrepareForEditing(aWindow); NS_ENSURE_SUCCESS(rv, rv); // Setup the command controllers again. @@ -1278,7 +1252,7 @@ nsresult nsEditingSession::ReattachToWindow(mozIDOMWindowProxy* aWindow) { NS_ENSURE_SUCCESS(rv, rv); if (mComposerCommandsUpdater) { - mComposerCommandsUpdater->Init(window); + mComposerCommandsUpdater->Init(*aWindow); } // Get editor @@ -1307,7 +1281,7 @@ nsresult nsEditingSession::ReattachToWindow(mozIDOMWindowProxy* aWindow) { NS_ENSURE_SUCCESS(rv, rv); // Set context on all controllers to be the editor - rv = SetEditorOnControllers(aWindow, htmlEditor); + rv = SetEditorOnControllers(*aWindow, htmlEditor); NS_ENSURE_SUCCESS(rv, rv); #ifdef DEBUG diff --git a/editor/composer/nsEditingSession.h b/editor/composer/nsEditingSession.h index ac0e4f49a32f..5dd9e4d262d9 100644 --- a/editor/composer/nsEditingSession.h +++ b/editor/composer/nsEditingSession.h @@ -30,7 +30,6 @@ class nsITimer; class nsIChannel; class nsIControllers; class nsIDocShell; -class nsIEditor; class nsIWebProgress; namespace mozilla { @@ -53,6 +52,18 @@ class nsEditingSession final : public nsIEditingSession, // nsIEditingSession NS_DECL_NSIEDITINGSESSION + /** + * Removes all the editor's controllers/listeners etc and makes the window + * uneditable. + */ + nsresult DetachFromWindow(nsPIDOMWindowOuter* aWindow); + + /** + * Undos DetachFromWindow(), reattaches this editing session/editor + * to the window. + */ + nsresult ReattachToWindow(nsPIDOMWindowOuter* aWindow); + protected: virtual ~nsEditingSession(); @@ -65,6 +76,17 @@ class nsEditingSession final : public nsIEditingSession, nsresult SetContextOnControllerById(nsIControllers* aControllers, nsISupports* aContext, uint32_t aID); + /** + * Set the editor on the controller(s) for this window + */ + nsresult SetEditorOnControllers(nsPIDOMWindowOuter& aWindow, + mozilla::HTMLEditor* aEditor); + + /** + * Setup editor and related support objects + */ + MOZ_CAN_RUN_SCRIPT nsresult SetupEditorOnWindow(nsPIDOMWindowOuter& aWindow); + nsresult PrepareForEditing(nsPIDOMWindowOuter* aWindow); static void TimerCallback(nsITimer* aTimer, void* aClosure); diff --git a/editor/composer/nsIEditingSession.idl b/editor/composer/nsIEditingSession.idl index f80d482835f6..a26b0add2570 100644 --- a/editor/composer/nsIEditingSession.idl +++ b/editor/composer/nsIEditingSession.idl @@ -67,31 +67,10 @@ interface nsIEditingSession : nsISupports */ nsIEditor getEditorForWindow(in mozIDOMWindowProxy window); - /** - * Setup editor and related support objects - */ - [can_run_script] - void setupEditorOnWindow(in mozIDOMWindowProxy window); - /** * Destroy editor and related support objects */ - void tearDownEditorOnWindow(in mozIDOMWindowProxy window); - - void setEditorOnControllers(in mozIDOMWindowProxy aWindow, - in nsIEditor aEditor); - - /** - * Removes all the editor's controllers/listeners etc and makes the window - * uneditable. - */ - void detachFromWindow(in mozIDOMWindowProxy aWindow); - - /** - * Undos detachFromWindow(), reattaches this editing session/editor - * to the window. - */ - void reattachToWindow(in mozIDOMWindowProxy aWindow); + [noscript] void tearDownEditorOnWindow(in mozIDOMWindowProxy window); %{C++ /** diff --git a/editor/libeditor/HTMLAnonymousNodeEditor.cpp b/editor/libeditor/HTMLAnonymousNodeEditor.cpp index 76ae0bb38216..51617c619ee2 100644 --- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp +++ b/editor/libeditor/HTMLAnonymousNodeEditor.cpp @@ -92,28 +92,18 @@ NS_IMPL_ISUPPORTS(ElementDeletionObserver, nsIMutationObserver) void ElementDeletionObserver::ParentChainChanged(nsIContent* aContent) { // If the native anonymous content has been unbound already in // DeleteRefToAnonymousNode, mNativeAnonNode's parentNode is null. - if (aContent == mObservedElement && mNativeAnonNode && - mNativeAnonNode->GetParentNode() == aContent) { - // If the observed node has been moved to another document, there isn't much - // we can do easily. But at least be safe and unbind the native anonymous - // content and stop observing changes. - if (mNativeAnonNode->OwnerDoc() != mObservedElement->OwnerDoc()) { - mObservedElement->RemoveMutationObserver(this); - mObservedElement = nullptr; - mNativeAnonNode->RemoveMutationObserver(this); - mNativeAnonNode->UnbindFromTree(); - mNativeAnonNode = nullptr; - NS_RELEASE_THIS(); - return; - } - - // We're staying in the same document, just rebind the native anonymous - // node so that the subtree root points to the right object etc. - mNativeAnonNode->UnbindFromTree(); - - BindContext context(*mObservedElement, BindContext::ForNativeAnonymous); - mNativeAnonNode->BindToTree(context, *mObservedElement); + if (aContent != mObservedElement || !mNativeAnonNode || + mNativeAnonNode->GetParent() != aContent) { + return; } + + ManualNACPtr::RemoveContentFromNACArray(mNativeAnonNode); + + mObservedElement->RemoveMutationObserver(this); + mObservedElement = nullptr; + mNativeAnonNode->RemoveMutationObserver(this); + mNativeAnonNode = nullptr; + NS_RELEASE_THIS(); } void ElementDeletionObserver::NodeWillBeDestroyed(const nsINode* aNode) { diff --git a/editor/libeditor/ManualNAC.h b/editor/libeditor/ManualNAC.h index d772b47dfe1e..1e0e03e70e99 100644 --- a/editor/libeditor/ManualNAC.h +++ b/editor/libeditor/ManualNAC.h @@ -60,25 +60,29 @@ class ManualNACPtr final { } RefPtr ptr = mPtr.forget(); - nsIContent* parentContent = ptr->GetParent(); + RemoveContentFromNACArray(ptr); + } + + static void RemoveContentFromNACArray(nsIContent* aAnonymousContent) { + nsIContent* parentContent = aAnonymousContent->GetParent(); if (!parentContent) { NS_WARNING("Potentially leaking manual NAC"); return; } // Remove reference from the parent element. - auto nac = static_cast( + auto* nac = static_cast( parentContent->GetProperty(nsGkAtoms::manualNACProperty)); // Document::AdoptNode might remove all properties before destroying editor. // So we have to consider that NAC could be already removed. if (nac) { - nac->RemoveElement(ptr); + nac->RemoveElement(aAnonymousContent); if (nac->IsEmpty()) { parentContent->DeleteProperty(nsGkAtoms::manualNACProperty); } } - ptr->UnbindFromTree(); + aAnonymousContent->UnbindFromTree(); } Element* get() const { return mPtr.get(); } diff --git a/editor/libeditor/crashtests/1556799.html b/editor/libeditor/crashtests/1556799.html new file mode 100644 index 000000000000..c83fcd618d8a --- /dev/null +++ b/editor/libeditor/crashtests/1556799.html @@ -0,0 +1,11 @@ + +
+