diff --git a/accessible/mac/mozAccessible.mm b/accessible/mac/mozAccessible.mm index 6e7fb540520..c1ae2b43cc6 100644 --- a/accessible/mac/mozAccessible.mm +++ b/accessible/mac/mozAccessible.mm @@ -355,10 +355,12 @@ ConvertToNSArray(nsTArray& aArray) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - AccessibleWrap* accWrap = [self getGeckoAccessible]; - if (accWrap) { - Accessible* acc = accWrap->GetChildAt(i); - return acc ? GetNativeFromGeckoAccessible(acc) : nil; + if (AccessibleWrap* accWrap = [self getGeckoAccessible]) { + Accessible* child = accWrap->GetChildAt(i); + return child ? GetNativeFromGeckoAccessible(child) : nil; + } else if (ProxyAccessible* proxy = [self getProxyAccessible]) { + ProxyAccessible* child = proxy->ChildAt(i); + return child ? GetNativeFromProxy(child) : nil; } return nil; @@ -849,12 +851,14 @@ ConvertToNSArray(nsTArray& aArray) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - AccessibleWrap* accWrap = [self getGeckoAccessible]; - if (!accWrap) + nsIntRect rect; + if (AccessibleWrap* accWrap = [self getGeckoAccessible]) + rect = accWrap->Bounds(); + else if (ProxyAccessible* proxy = [self getProxyAccessible]) + rect = proxy->Bounds(); + else return nil; - nsIntRect rect = accWrap->Bounds(); - NSScreen* mainView = [[NSScreen screens] objectAtIndex:0]; CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(mainView); NSPoint p = NSMakePoint(static_cast(rect.x) / scaleFactor, @@ -869,11 +873,14 @@ ConvertToNSArray(nsTArray& aArray) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - AccessibleWrap* accWrap = [self getGeckoAccessible]; - if (!accWrap) + nsIntRect rect; + if (AccessibleWrap* accWrap = [self getGeckoAccessible]) + rect = accWrap->Bounds(); + else if (ProxyAccessible* proxy = [self getProxyAccessible]) + rect = proxy->Bounds(); + else return nil; - nsIntRect rect = accWrap->Bounds(); CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor([[NSScreen screens] objectAtIndex:0]); return [NSValue valueWithSize:NSMakeSize(static_cast(rect.width) / scaleFactor, diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 38f682c5c4e..136aace6507 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -1118,9 +1118,6 @@ pref("services.mobileid.server.uri", "https://msisdn.services.mozilla.com"); pref("dom.mapped_arraybuffer.enabled", true); #endif -// BroadcastChannel API -pref("dom.broadcastChannel.enabled", true); - // SystemUpdate API pref("dom.system_update.enabled", true); diff --git a/b2g/config/mozconfigs/linux32_gecko/debug b/b2g/config/mozconfigs/linux32_gecko/debug index c3bbe38a452..9ba6ac90f90 100644 --- a/b2g/config/mozconfigs/linux32_gecko/debug +++ b/b2g/config/mozconfigs/linux32_gecko/debug @@ -35,6 +35,6 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt . "$topsrcdir/b2g/config/mozconfigs/common.override" diff --git a/b2g/config/mozconfigs/linux32_gecko/nightly b/b2g/config/mozconfigs/linux32_gecko/nightly index 2dcad1b375d..251ab2ccd06 100644 --- a/b2g/config/mozconfigs/linux32_gecko/nightly +++ b/b2g/config/mozconfigs/linux32_gecko/nightly @@ -34,7 +34,7 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt # Build simulator xpi and phone tweaks for b2g-desktop FXOS_SIMULATOR=1 diff --git a/b2g/config/mozconfigs/linux64_gecko/debug b/b2g/config/mozconfigs/linux64_gecko/debug index 1d1c3c60784..71f4ec3ab0b 100644 --- a/b2g/config/mozconfigs/linux64_gecko/debug +++ b/b2g/config/mozconfigs/linux64_gecko/debug @@ -35,6 +35,6 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt . "$topsrcdir/b2g/config/mozconfigs/common.override" diff --git a/b2g/config/mozconfigs/linux64_gecko/nightly b/b2g/config/mozconfigs/linux64_gecko/nightly index 5dfe2819956..8ac486ed721 100644 --- a/b2g/config/mozconfigs/linux64_gecko/nightly +++ b/b2g/config/mozconfigs/linux64_gecko/nightly @@ -34,7 +34,7 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt # Build simulator xpi and phone tweaks for b2g-desktop FXOS_SIMULATOR=1 diff --git a/b2g/config/mozconfigs/macosx64_gecko/debug b/b2g/config/mozconfigs/macosx64_gecko/debug index a3d19eb395c..43e4bc182f4 100644 --- a/b2g/config/mozconfigs/macosx64_gecko/debug +++ b/b2g/config/mozconfigs/macosx64_gecko/debug @@ -32,6 +32,6 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt . "$topsrcdir/b2g/config/mozconfigs/common.override" diff --git a/b2g/config/mozconfigs/macosx64_gecko/nightly b/b2g/config/mozconfigs/macosx64_gecko/nightly index a1b5b061a07..d13ffe72363 100644 --- a/b2g/config/mozconfigs/macosx64_gecko/nightly +++ b/b2g/config/mozconfigs/macosx64_gecko/nightly @@ -30,7 +30,7 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt # Build simulator xpi and phone tweaks for b2g-desktop FXOS_SIMULATOR=1 diff --git a/b2g/config/mozconfigs/win32_gecko/debug b/b2g/config/mozconfigs/win32_gecko/debug index e67d627e2fe..24ba78e034d 100644 --- a/b2g/config/mozconfigs/win32_gecko/debug +++ b/b2g/config/mozconfigs/win32_gecko/debug @@ -29,6 +29,6 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt . "$topsrcdir/b2g/config/mozconfigs/common.override" diff --git a/b2g/config/mozconfigs/win32_gecko/nightly b/b2g/config/mozconfigs/win32_gecko/nightly index 9bb1203ae91..19402d86b78 100644 --- a/b2g/config/mozconfigs/win32_gecko/nightly +++ b/b2g/config/mozconfigs/win32_gecko/nightly @@ -27,7 +27,7 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP GAIADIR=$topsrcdir/gaia # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt # Build simulator xpi and phone tweaks for b2g-desktop FXOS_SIMULATOR=1 diff --git a/b2g/config/tooltool-manifests/linux32/releng.manifest b/b2g/config/tooltool-manifests/linux32/releng.manifest index 4b9f7ad4ed1..604e98b09cd 100644 --- a/b2g/config/tooltool-manifests/linux32/releng.manifest +++ b/b2g/config/tooltool-manifests/linux32/releng.manifest @@ -14,10 +14,10 @@ "unpack": true }, { -"size": 31057326, -"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", +"size": 31078810, +"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c", "algorithm": "sha512", -"filename": "moztt.tar.bz2", +"filename": "moz-tt.tar.bz2", "unpack": true } ] diff --git a/b2g/config/tooltool-manifests/linux64/releng.manifest b/b2g/config/tooltool-manifests/linux64/releng.manifest index 4b9f7ad4ed1..604e98b09cd 100644 --- a/b2g/config/tooltool-manifests/linux64/releng.manifest +++ b/b2g/config/tooltool-manifests/linux64/releng.manifest @@ -14,10 +14,10 @@ "unpack": true }, { -"size": 31057326, -"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", +"size": 31078810, +"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c", "algorithm": "sha512", -"filename": "moztt.tar.bz2", +"filename": "moz-tt.tar.bz2", "unpack": true } ] diff --git a/b2g/config/tooltool-manifests/macosx64/releng.manifest b/b2g/config/tooltool-manifests/macosx64/releng.manifest index 0867e800a5c..a4ea213fb13 100644 --- a/b2g/config/tooltool-manifests/macosx64/releng.manifest +++ b/b2g/config/tooltool-manifests/macosx64/releng.manifest @@ -17,10 +17,10 @@ "unpack": true }, { -"size": 31057326, -"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", +"size": 31078810, +"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c", "algorithm": "sha512", -"filename": "moztt.tar.bz2", +"filename": "moz-tt.tar.bz2", "unpack": true } ] diff --git a/b2g/config/tooltool-manifests/win32/releng.manifest b/b2g/config/tooltool-manifests/win32/releng.manifest index 8cbd9fcee38..f0592ee141f 100644 --- a/b2g/config/tooltool-manifests/win32/releng.manifest +++ b/b2g/config/tooltool-manifests/win32/releng.manifest @@ -6,10 +6,10 @@ "filename": "mozmake.exe" }, { -"size": 31057326, -"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", +"size": 31078810, +"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c", "algorithm": "sha512", -"filename": "moztt.tar.bz2", +"filename": "moz-tt.tar.bz2", "unpack": true }, { diff --git a/b2g/dev/config/mozconfigs/linux64/mulet b/b2g/dev/config/mozconfigs/linux64/mulet index b2f7dd3b6bb..f2b8977b0de 100644 --- a/b2g/dev/config/mozconfigs/linux64/mulet +++ b/b2g/dev/config/mozconfigs/linux64/mulet @@ -8,4 +8,4 @@ ac_add_options --enable-default-toolkit=cairo-gtk2 ac_add_options --enable-application=b2g/dev # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt diff --git a/b2g/dev/config/mozconfigs/macosx64/mulet b/b2g/dev/config/mozconfigs/macosx64/mulet index 93bbf41eebd..901e9892cc6 100644 --- a/b2g/dev/config/mozconfigs/macosx64/mulet +++ b/b2g/dev/config/mozconfigs/macosx64/mulet @@ -24,7 +24,7 @@ ac_add_options --enable-warnings-as-errors export MOZ_PACKAGE_JSSHELL=1 # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt . "$topsrcdir/build/mozconfig.common.override" . "$topsrcdir/build/mozconfig.cache" diff --git a/b2g/dev/config/mozconfigs/win32/mulet b/b2g/dev/config/mozconfigs/win32/mulet index 4cfdf801183..f5a43bd6a33 100644 --- a/b2g/dev/config/mozconfigs/win32/mulet +++ b/b2g/dev/config/mozconfigs/win32/mulet @@ -10,4 +10,4 @@ MOZ_AUTOMATION_SDK=0 ac_add_options --enable-application=b2g/dev # Include Firefox OS fonts. -MOZTTDIR=$topsrcdir/moztt +MOZTTDIR=$topsrcdir/moz-tt diff --git a/b2g/dev/config/tooltool-manifests/linux64/releng.manifest b/b2g/dev/config/tooltool-manifests/linux64/releng.manifest index 4b9f7ad4ed1..604e98b09cd 100644 --- a/b2g/dev/config/tooltool-manifests/linux64/releng.manifest +++ b/b2g/dev/config/tooltool-manifests/linux64/releng.manifest @@ -14,10 +14,10 @@ "unpack": true }, { -"size": 31057326, -"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", +"size": 31078810, +"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c", "algorithm": "sha512", -"filename": "moztt.tar.bz2", +"filename": "moz-tt.tar.bz2", "unpack": true } ] diff --git a/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest b/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest index 0867e800a5c..a4ea213fb13 100644 --- a/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest +++ b/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest @@ -17,10 +17,10 @@ "unpack": true }, { -"size": 31057326, -"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", +"size": 31078810, +"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c", "algorithm": "sha512", -"filename": "moztt.tar.bz2", +"filename": "moz-tt.tar.bz2", "unpack": true } ] diff --git a/b2g/dev/config/tooltool-manifests/win32/releng.manifest b/b2g/dev/config/tooltool-manifests/win32/releng.manifest index a01b7781244..a5f5e436a93 100644 --- a/b2g/dev/config/tooltool-manifests/win32/releng.manifest +++ b/b2g/dev/config/tooltool-manifests/win32/releng.manifest @@ -13,10 +13,10 @@ "unpack": true }, { -"size": 31057326, -"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", +"size": 31078810, +"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c", "algorithm": "sha512", -"filename": "moztt.tar.bz2", +"filename": "moz-tt.tar.bz2", "unpack": true } ] diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index ce470b54f14..2a57cba39a4 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -644,6 +644,7 @@ @RESPATH@/components/AppsService.manifest @RESPATH@/components/Push.js @RESPATH@/components/Push.manifest +@RESPATH@/components/PushClient.js @RESPATH@/components/PushNotificationService.js @RESPATH@/components/PushServiceLauncher.js @@ -710,6 +711,7 @@ @RESPATH@/components/nsUrlClassifierHashCompleter.js @RESPATH@/components/nsUrlClassifierListManager.js @RESPATH@/components/nsUrlClassifierLib.js +@RESPATH@/components/PrivateBrowsingTrackingProtectionWhitelist.js @RESPATH@/components/url-classifier.xpt ; GNOME hooks diff --git a/browser/base/content/aboutaccounts/aboutaccounts.js b/browser/base/content/aboutaccounts/aboutaccounts.js index 1df36272078..6fbfb9f3c1a 100644 --- a/browser/base/content/aboutaccounts/aboutaccounts.js +++ b/browser/base/content/aboutaccounts/aboutaccounts.js @@ -148,8 +148,13 @@ let wrapper = { if (accountData.customizeSync) { Services.prefs.setBoolPref(PREF_SYNC_SHOW_CUSTOMIZATION, true); - delete accountData.customizeSync; } + delete accountData.customizeSync; + // sessionTokenContext is erroneously sent by the content server. + // https://github.com/mozilla/fxa-content-server/issues/2766 + // To avoid having the FxA storage manager not knowing what to do with + // it we delete it here. + delete accountData.sessionTokenContext; // We need to confirm a relink - see shouldAllowRelink for more let newAccountEmail = accountData.email; diff --git a/browser/base/content/browser-trackingprotection.js b/browser/base/content/browser-trackingprotection.js index 2d97dc85886..29f72bcf703 100644 --- a/browser/base/content/browser-trackingprotection.js +++ b/browser/base/content/browser-trackingprotection.js @@ -116,8 +116,12 @@ let TrackingProtection = { // Add the current host in the 'trackingprotection' consumer of // the permission manager using a normalized URI. This effectively // places this host on the tracking protection allowlist. - Services.perms.add(normalizedUrl, - "trackingprotection", Services.perms.ALLOW_ACTION); + if (PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser)) { + PrivateBrowsingUtils.addToTrackingAllowlist(normalizedUrl); + } else { + Services.perms.add(normalizedUrl, + "trackingprotection", Services.perms.ALLOW_ACTION); + } // Telemetry for disable protection. this.eventsHistogram.add(1); @@ -133,8 +137,11 @@ let TrackingProtection = { "https://" + gBrowser.selectedBrowser.currentURI.hostPort, null, null); - Services.perms.remove(normalizedUrl, - "trackingprotection"); + if (PrivateBrowsingUtils.isBrowserPrivate(gBrowser.selectedBrowser)) { + PrivateBrowsingUtils.removeFromTrackingAllowlist(normalizedUrl); + } else { + Services.perms.remove(normalizedUrl, "trackingprotection"); + } // Telemetry for enable protection. this.eventsHistogram.add(2); diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini index f4998abb1c0..33805be1aed 100644 --- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -431,6 +431,10 @@ tags = trackingprotection support-files = trackingPage.html benignPage.html +[browser_trackingUI_5.js] +tags = trackingprotection +support-files = + trackingPage.html [browser_typeAheadFind.js] skip-if = buildapp == 'mulet' [browser_unknownContentType_title.js] diff --git a/browser/base/content/test/general/browser_trackingUI_5.js b/browser/base/content/test/general/browser_trackingUI_5.js new file mode 100644 index 00000000000..ec178c9b1f2 --- /dev/null +++ b/browser/base/content/test/general/browser_trackingUI_5.js @@ -0,0 +1,122 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Test that sites added to the Tracking Protection whitelist in private +// browsing mode don't persist once the private browsing window closes. + +const PB_PREF = "privacy.trackingprotection.pbmode.enabled"; +const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html"; +let TrackingProtection = null; +let browser = null; +let {UrlClassifierTestUtils} = Cu.import("resource://testing-common/UrlClassifierTestUtils.jsm", {}); + +registerCleanupFunction(function() { + TrackingProtection = browser = null; + UrlClassifierTestUtils.cleanupTestTrackers(); +}); + +function hidden(sel) { + let win = browser.ownerGlobal; + let el = win.document.querySelector(sel); + let display = win.getComputedStyle(el).getPropertyValue("display", null); + return display === "none"; +} + +function clickButton(sel) { + let win = browser.ownerGlobal; + let el = win.document.querySelector(sel); + el.doCommand(); +} + +function testTrackingPage(window) { + info("Tracking content must be blocked"); + ok(!TrackingProtection.container.hidden, "The container is visible"); + is(TrackingProtection.content.getAttribute("state"), "blocked-tracking-content", + 'content: state="blocked-tracking-content"'); + is(TrackingProtection.icon.getAttribute("state"), "blocked-tracking-content", + 'icon: state="blocked-tracking-content"'); + + ok(!hidden("#tracking-protection-icon"), "icon is visible"); + ok(hidden("#tracking-action-block"), "blockButton is hidden"); + + ok(hidden("#tracking-action-unblock"), "unblockButton is hidden"); + ok(!hidden("#tracking-action-unblock-private"), "unblockButtonPrivate is visible"); + + // Make sure that the blocked tracking elements message appears + ok(hidden("#tracking-not-detected"), "labelNoTracking is hidden"); + ok(hidden("#tracking-loaded"), "labelTrackingLoaded is hidden"); + ok(!hidden("#tracking-blocked"), "labelTrackingBlocked is visible"); +} + +function testTrackingPageUnblocked() { + info("Tracking content must be white-listed and not blocked"); + ok(!TrackingProtection.container.hidden, "The container is visible"); + is(TrackingProtection.content.getAttribute("state"), "loaded-tracking-content", + 'content: state="loaded-tracking-content"'); + is(TrackingProtection.icon.getAttribute("state"), "loaded-tracking-content", + 'icon: state="loaded-tracking-content"'); + + ok(!hidden("#tracking-protection-icon"), "icon is visible"); + ok(!hidden("#tracking-action-block"), "blockButton is visible"); + ok(hidden("#tracking-action-unblock"), "unblockButton is hidden"); + + // Make sure that the blocked tracking elements message appears + ok(hidden("#tracking-not-detected"), "labelNoTracking is hidden"); + ok(!hidden("#tracking-loaded"), "labelTrackingLoaded is visible"); + ok(hidden("#tracking-blocked"), "labelTrackingBlocked is hidden"); +} + +add_task(function* testExceptionAddition() { + yield UrlClassifierTestUtils.addTestTrackers(); + let privateWin = yield promiseOpenAndLoadWindow({private: true}, true); + browser = privateWin.gBrowser; + let tab = browser.selectedTab = browser.addTab(); + + TrackingProtection = browser.ownerGlobal.TrackingProtection; + yield pushPrefs([PB_PREF, true]); + + ok(TrackingProtection.enabled, "TP is enabled after setting the pref"); + + info("Load a test page containing tracking elements"); + yield promiseTabLoadEvent(tab, TRACKING_PAGE); + + testTrackingPage(tab.ownerDocument.defaultView); + + info("Disable TP for the page (which reloads the page)"); + let tabReloadPromise = promiseTabLoadEvent(tab); + clickButton("#tracking-action-unblock"); + yield tabReloadPromise; + testTrackingPageUnblocked(); + + info("Test that the exception is remembered across tabs in the same private window"); + tab = browser.selectedTab = browser.addTab(); + + info("Load a test page containing tracking elements"); + yield promiseTabLoadEvent(tab, TRACKING_PAGE); + testTrackingPageUnblocked(); + + yield promiseWindowClosed(privateWin); +}); + +add_task(function* testExceptionPersistence() { + info("Open another private browsing window"); + let privateWin = yield promiseOpenAndLoadWindow({private: true}, true); + browser = privateWin.gBrowser; + let tab = browser.selectedTab = browser.addTab(); + + TrackingProtection = browser.ownerGlobal.TrackingProtection; + ok(TrackingProtection.enabled, "TP is still enabled"); + + info("Load a test page containing tracking elements"); + yield promiseTabLoadEvent(tab, TRACKING_PAGE); + + testTrackingPage(tab.ownerDocument.defaultView); + + info("Disable TP for the page (which reloads the page)"); + let tabReloadPromise = promiseTabLoadEvent(tab); + clickButton("#tracking-action-unblock"); + yield tabReloadPromise; + testTrackingPageUnblocked(); + + privateWin.close(); +}); diff --git a/browser/base/content/test/plugins/head.js b/browser/base/content/test/plugins/head.js index c1290ed19eb..b5633e04d20 100644 --- a/browser/base/content/test/plugins/head.js +++ b/browser/base/content/test/plugins/head.js @@ -1,7 +1,5 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Promise", - "resource://gre/modules/Promise.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", @@ -35,18 +33,14 @@ function promiseInitContentBlocklistSvc(aBrowser) * @returns a Promise that resolves to true after the time has elapsed */ function waitForMs(aMs) { - let deferred = Promise.defer(); - let startTime = Date.now(); - setTimeout(done, aMs); - function done() { - deferred.resolve(true); - } - return deferred.promise; + return new Promise((resolve) => { + setTimeout(done, aMs); + function done() { + resolve(true); + } + }); } - -// DOM Promise fails for unknown reasons here, so we're using -// resource://gre/modules/Promise.jsm. function waitForEvent(subject, eventName, checkFn, useCapture, useUntrusted) { return new Promise((resolve, reject) => { subject.addEventListener(eventName, function listener(event) { @@ -84,33 +78,33 @@ function waitForEvent(subject, eventName, checkFn, useCapture, useUntrusted) { * @rejects if a valid load event is not received within a meaningful interval */ function promiseTabLoadEvent(tab, url, eventType="load") { - let deferred = Promise.defer(); - info("Wait tab event: " + eventType); + return new Promise((resolve, reject) => { + info("Wait tab event: " + eventType); - function handle(event) { - if (event.originalTarget != tab.linkedBrowser.contentDocument || - event.target.location.href == "about:blank" || - (url && event.target.location.href != url)) { - info("Skipping spurious '" + eventType + "'' event" + - " for " + event.target.location.href); - return; + function handle(event) { + if (event.originalTarget != tab.linkedBrowser.contentDocument || + event.target.location.href == "about:blank" || + (url && event.target.location.href != url)) { + info("Skipping spurious '" + eventType + "'' event" + + " for " + event.target.location.href); + return; + } + clearTimeout(timeout); + tab.linkedBrowser.removeEventListener(eventType, handle, true); + info("Tab event received: " + eventType); + resolve(event); } - clearTimeout(timeout); - tab.linkedBrowser.removeEventListener(eventType, handle, true); - info("Tab event received: " + eventType); - deferred.resolve(event); - } - let timeout = setTimeout(() => { - tab.linkedBrowser.removeEventListener(eventType, handle, true); - deferred.reject(new Error("Timed out while waiting for a '" + eventType + "'' event")); - }, 30000); + let timeout = setTimeout(() => { + tab.linkedBrowser.removeEventListener(eventType, handle, true); + reject(new Error("Timed out while waiting for a '" + eventType + "'' event")); + }, 30000); - tab.linkedBrowser.addEventListener(eventType, handle, true, true); - if (url) { - tab.linkedBrowser.loadURI(url); - } - return deferred.promise; + tab.linkedBrowser.addEventListener(eventType, handle, true, true); + if (url) { + tab.linkedBrowser.loadURI(url); + } + }); } function waitForCondition(condition, nextTest, errorMsg, aTries, aWait) { @@ -139,11 +133,11 @@ function waitForCondition(condition, nextTest, errorMsg, aTries, aWait) { // Waits for a conditional function defined by the caller to return true. function promiseForCondition(aConditionFn, aMessage, aTries, aWait) { - let deferred = Promise.defer(); - waitForCondition(aConditionFn, deferred.resolve, - (aMessage || "Condition didn't pass."), - aTries, aWait); - return deferred.promise; + return new Promise((resolve) => { + waitForCondition(aConditionFn, resolve, + (aMessage || "Condition didn't pass."), + aTries, aWait); + }); } // Returns the chrome side nsIPluginTag for this plugin @@ -298,17 +292,15 @@ function resetBlocklist() { // Insure there's a popup notification present. This test does not indicate // open state. aBrowser can be undefined. function promisePopupNotification(aName, aBrowser) { - let deferred = Promise.defer(); + return new Promise((resolve) => { + waitForCondition(() => PopupNotifications.getNotification(aName, aBrowser), + () => { + ok(!!PopupNotifications.getNotification(aName, aBrowser), + aName + " notification appeared"); - waitForCondition(() => PopupNotifications.getNotification(aName, aBrowser), - () => { - ok(!!PopupNotifications.getNotification(aName, aBrowser), - aName + " notification appeared"); - - deferred.resolve(); - }, "timeout waiting for popup notification " + aName); - - return deferred.promise; + resolve(); + }, "timeout waiting for popup notification " + aName); + }); } /** @@ -361,9 +353,9 @@ function waitForNotificationBar(notificationID, browser, callback) { } function promiseForNotificationBar(notificationID, browser) { - let deferred = Promise.defer(); - waitForNotificationBar(notificationID, browser, deferred.resolve); - return deferred.promise; + return new Promise((resolve) => { + waitForNotificationBar(notificationID, browser, resolve); + }); } /** @@ -386,9 +378,9 @@ function waitForNotificationShown(notification, callback) { } function promiseForNotificationShown(notification) { - let deferred = Promise.defer(); - waitForNotificationShown(notification, deferred.resolve); - return deferred.promise; + return new Promise((resolve) => { + waitForNotificationShown(notification, resolve); + }); } /** diff --git a/browser/components/customizableui/CustomizableWidgets.jsm b/browser/components/customizableui/CustomizableWidgets.jsm index ad2b69fddbe..76efb06ed6e 100644 --- a/browser/components/customizableui/CustomizableWidgets.jsm +++ b/browser/components/customizableui/CustomizableWidgets.jsm @@ -957,9 +957,8 @@ const CustomizableWidgets = [ type: "custom", label: "loop-call-button3.label", tooltiptext: "loop-call-button3.tooltiptext", + privateBrowsingTooltiptext: "loop-call-button3-pb.tooltiptext", defaultArea: CustomizableUI.AREA_NAVBAR, - // Not in private browsing, see bug 1108187. - showInPrivateBrowsing: false, introducedInVersion: 4, onBuild: function(aDocument) { // If we're not supposed to see the button, return zip. @@ -967,13 +966,21 @@ const CustomizableWidgets = [ return null; } + let isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(aDocument.defaultView); + let node = aDocument.createElementNS(kNSXUL, "toolbarbutton"); node.setAttribute("id", this.id); node.classList.add("toolbarbutton-1"); node.classList.add("chromeclass-toolbar-additional"); node.classList.add("badged-button"); node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label")); - node.setAttribute("tooltiptext", CustomizableUI.getLocalizedProperty(this, "tooltiptext")); + if (isWindowPrivate) + node.setAttribute("disabled", "true"); + let tooltiptext = isWindowPrivate ? + CustomizableUI.getLocalizedProperty(this, "privateBrowsingTooltiptext", + [CustomizableUI.getLocalizedProperty(this, "label")]) : + CustomizableUI.getLocalizedProperty(this, "tooltiptext"); + node.setAttribute("tooltiptext", tooltiptext); node.setAttribute("removable", "true"); node.addEventListener("command", function(event) { aDocument.defaultView.LoopUI.togglePanel(event); diff --git a/browser/components/customizableui/test/browser_946320_tabs_from_other_computers.js b/browser/components/customizableui/test/browser_946320_tabs_from_other_computers.js index ff3785519ba..252b6b94cb3 100644 --- a/browser/components/customizableui/test/browser_946320_tabs_from_other_computers.js +++ b/browser/components/customizableui/test/browser_946320_tabs_from_other_computers.js @@ -119,7 +119,7 @@ function configureFxAccountIdentity() { let storageManager = new MockFxaStorageManager(); // and init storage with our user. storageManager.initialize(user); - return new AccountState(this, storageManager); + return new AccountState(storageManager); }, getCertificate(data, keyPair, mustBeValidUntil) { this.cert = { diff --git a/browser/components/loop/content/js/conversationViews.js b/browser/components/loop/content/js/conversationViews.js index a8054e899ed..9e6e6886537 100644 --- a/browser/components/loop/content/js/conversationViews.js +++ b/browser/components/loop/content/js/conversationViews.js @@ -570,13 +570,15 @@ loop.conversationViews = (function(mozL10n) { var OngoingConversationView = React.createClass({displayName: "OngoingConversationView", mixins: [ - loop.store.StoreMixin("conversationStore"), sharedMixins.MediaSetupMixin ], propTypes: { // local audio: React.PropTypes.object, + // We pass conversationStore here rather than use the mixin, to allow + // easy configurability for the ui-showcase. + conversationStore: React.PropTypes.instanceOf(loop.store.ConversationStore).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, // The poster URLs are for UI-showcase testing and development. localPosterUrl: React.PropTypes.string, @@ -597,7 +599,17 @@ loop.conversationViews = (function(mozL10n) { }, getInitialState: function() { - return this.getStoreState(); + return this.props.conversationStore.getStoreState(); + }, + + componentWillMount: function() { + this.props.conversationStore.on("change", function() { + this.setState(this.props.conversationStore.getStoreState()); + }, this); + }, + + componentWillUnmount: function() { + this.props.conversationStore.off("change", null, this); }, componentDidMount: function() { @@ -633,6 +645,30 @@ loop.conversationViews = (function(mozL10n) { })); }, + /** + * Should we render a visual cue to the user (e.g. a spinner) that a local + * stream is on its way from the camera? + * + * @returns {boolean} + * @private + */ + _isLocalLoading: function () { + return !this.state.localSrcVideoObject && !this.props.localPosterUrl; + }, + + /** + * Should we render a visual cue to the user (e.g. a spinner) that a remote + * stream is on its way from the other user? + * + * @returns {boolean} + * @private + */ + _isRemoteLoading: function() { + return !!(!this.state.remoteSrcVideoObject && + !this.props.remotePosterUrl && + !this.state.mediaConnected); + }, + shouldRenderRemoteVideo: function() { if (this.props.mediaConnected) { // If remote video is not enabled, we're muted, so we'll show an avatar @@ -646,41 +682,32 @@ loop.conversationViews = (function(mozL10n) { }, render: function() { - var localStreamClasses = React.addons.classSet({ - local: true, - "local-stream": true, - "local-stream-audio": !this.props.video.enabled - }); - return ( - React.createElement("div", {className: "video-layout-wrapper"}, - React.createElement("div", {className: "conversation"}, - React.createElement("div", {className: "media nested"}, - React.createElement("div", {className: "video_wrapper remote_wrapper"}, - React.createElement("div", {className: "video_inner remote focus-stream"}, - React.createElement(sharedViews.MediaView, {displayAvatar: !this.shouldRenderRemoteVideo(), - isLoading: false, - mediaType: "remote", - posterUrl: this.props.remotePosterUrl, - srcVideoObject: this.state.remoteSrcVideoObject}) - ) - ), - React.createElement("div", {className: localStreamClasses}, - React.createElement(sharedViews.MediaView, {displayAvatar: !this.props.video.enabled, - isLoading: false, - mediaType: "local", - posterUrl: this.props.localPosterUrl, - srcVideoObject: this.state.localSrcVideoObject}) - ) - ), - React.createElement(loop.shared.views.ConversationToolbar, { - audio: this.props.audio, - dispatcher: this.props.dispatcher, - edit: { visible: false, enabled: false}, - hangup: this.hangup, - publishStream: this.publishStream, - video: this.props.video}) - ) + React.createElement("div", {className: "desktop-call-wrapper"}, + React.createElement(sharedViews.MediaLayoutView, { + dispatcher: this.props.dispatcher, + displayScreenShare: false, + isLocalLoading: this._isLocalLoading(), + isRemoteLoading: this._isRemoteLoading(), + isScreenShareLoading: false, + localPosterUrl: this.props.localPosterUrl, + localSrcVideoObject: this.state.localSrcVideoObject, + localVideoMuted: !this.props.video.enabled, + matchMedia: this.state.matchMedia || window.matchMedia.bind(window), + remotePosterUrl: this.props.remotePosterUrl, + remoteSrcVideoObject: this.state.remoteSrcVideoObject, + renderRemoteVideo: this.shouldRenderRemoteVideo(), + screenSharePosterUrl: null, + screenShareVideoObject: this.state.screenShareVideoObject, + showContextRoomName: false, + useDesktopPaths: true}), + React.createElement(loop.shared.views.ConversationToolbar, { + audio: this.props.audio, + dispatcher: this.props.dispatcher, + edit: { visible: false, enabled: false}, + hangup: this.hangup, + publishStream: this.publishStream, + video: this.props.video}) ) ); } @@ -778,6 +805,7 @@ loop.conversationViews = (function(mozL10n) { case CALL_STATES.ONGOING: { return (React.createElement(OngoingConversationView, { audio: {enabled: !this.state.audioMuted}, + conversationStore: this.getStore(), dispatcher: this.props.dispatcher, mediaConnected: this.state.mediaConnected, remoteSrcVideoObject: this.state.remoteSrcVideoObject, diff --git a/browser/components/loop/content/js/conversationViews.jsx b/browser/components/loop/content/js/conversationViews.jsx index 751c08309cb..cc04355dd19 100644 --- a/browser/components/loop/content/js/conversationViews.jsx +++ b/browser/components/loop/content/js/conversationViews.jsx @@ -570,13 +570,15 @@ loop.conversationViews = (function(mozL10n) { var OngoingConversationView = React.createClass({ mixins: [ - loop.store.StoreMixin("conversationStore"), sharedMixins.MediaSetupMixin ], propTypes: { // local audio: React.PropTypes.object, + // We pass conversationStore here rather than use the mixin, to allow + // easy configurability for the ui-showcase. + conversationStore: React.PropTypes.instanceOf(loop.store.ConversationStore).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, // The poster URLs are for UI-showcase testing and development. localPosterUrl: React.PropTypes.string, @@ -597,7 +599,17 @@ loop.conversationViews = (function(mozL10n) { }, getInitialState: function() { - return this.getStoreState(); + return this.props.conversationStore.getStoreState(); + }, + + componentWillMount: function() { + this.props.conversationStore.on("change", function() { + this.setState(this.props.conversationStore.getStoreState()); + }, this); + }, + + componentWillUnmount: function() { + this.props.conversationStore.off("change", null, this); }, componentDidMount: function() { @@ -633,6 +645,30 @@ loop.conversationViews = (function(mozL10n) { })); }, + /** + * Should we render a visual cue to the user (e.g. a spinner) that a local + * stream is on its way from the camera? + * + * @returns {boolean} + * @private + */ + _isLocalLoading: function () { + return !this.state.localSrcVideoObject && !this.props.localPosterUrl; + }, + + /** + * Should we render a visual cue to the user (e.g. a spinner) that a remote + * stream is on its way from the other user? + * + * @returns {boolean} + * @private + */ + _isRemoteLoading: function() { + return !!(!this.state.remoteSrcVideoObject && + !this.props.remotePosterUrl && + !this.state.mediaConnected); + }, + shouldRenderRemoteVideo: function() { if (this.props.mediaConnected) { // If remote video is not enabled, we're muted, so we'll show an avatar @@ -646,41 +682,32 @@ loop.conversationViews = (function(mozL10n) { }, render: function() { - var localStreamClasses = React.addons.classSet({ - local: true, - "local-stream": true, - "local-stream-audio": !this.props.video.enabled - }); - return ( -
-
-
-
-
- -
-
-
- -
-
- -
+
+ +
); } @@ -778,6 +805,7 @@ loop.conversationViews = (function(mozL10n) { case CALL_STATES.ONGOING: { return ( -
-
-
- -
-
- -
-
-
- -
- -
- -
-
- + + displayScreenShare={false} + isLocalLoading={this._isLocalLoading()} + isRemoteLoading={this._isRemoteLoading()} + isScreenShareLoading={false} + localPosterUrl={this.props.localPosterUrl} + localSrcVideoObject={this.state.localSrcVideoObject} + localVideoMuted={this.state.videoMuted} + matchMedia={this.state.matchMedia || window.matchMedia.bind(window)} + remotePosterUrl={this.props.remotePosterUrl} + remoteSrcVideoObject={this.state.remoteSrcVideoObject} + renderRemoteVideo={this.shouldRenderRemoteVideo()} + screenSharePosterUrl={null} + screenShareVideoObject={this.state.screenShareVideoObject} + showContextRoomName={false} + useDesktopPaths={true}> + + + +
); } diff --git a/browser/components/loop/content/shared/css/conversation.css b/browser/components/loop/content/shared/css/conversation.css index 62e73bd0668..1469a2a6a81 100644 --- a/browser/components/loop/content/shared/css/conversation.css +++ b/browser/components/loop/content/shared/css/conversation.css @@ -504,28 +504,6 @@ text-align: center; } -.fx-embedded .local-stream { - position: absolute; - right: 3px; - bottom: 5px; - /* next two lines are workaround for lack of object-fit; see bug 1020445 */ - max-width: 140px; - width: 30%; - height: 28%; - max-height: 105px; -} - -.fx-embedded .local-stream.room-preview { - top: 0px; - left: 0px; - right: 0px; - bottom: 0px; - height: 100%; - width: 100%; - max-width: none; - max-height: none; -} - .conversation .media.nested .focus-stream { display: inline-block; position: absolute; /* workaround for lack of object-fit; see bug 1020445 */ @@ -592,15 +570,11 @@ z-index: 1; } -.remote .avatar { +.remote > .avatar { /* make visually distinct from local avatar */ opacity: 0.25; } -.fx-embedded .media.nested { - min-height: 200px; -} - .fx-embedded-call-identifier { display: inline; width: 100%; @@ -675,7 +649,9 @@ * */ html, .fx-embedded, #main, .video-layout-wrapper, -.conversation { +.conversation, +.desktop-call-wrapper, +.desktop-room-wrapper { height: 100%; } @@ -935,7 +911,6 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item { border-top: 2px solid #444; border-bottom: 2px solid #444; padding: .5rem; - max-height: 400px; position: absolute; left: 0; bottom: 0; @@ -951,7 +926,7 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item { overflow-x: hidden; overflow-y: auto; /* Make the context view float atop the video elements. */ - z-index: 2; + z-index: 3; } .room-invitation-overlay .room-context { @@ -1087,12 +1062,12 @@ html[dir="rtl"] .room-context-btn-close { .standalone-room-wrapper > .media-layout { /* 50px is the header, 64px for toolbar, 3em is the footer. */ height: calc(100% - 50px - 64px - 3em); + margin: 0 10px; } .media-layout > .media-wrapper { display: flex; flex-flow: column wrap; - margin: 0 10px; height: 100%; } @@ -1139,6 +1114,14 @@ html[dir="rtl"] .room-context-btn-close { height: calc(100% - 300px); } +.desktop-call-wrapper > .media-layout > .media-wrapper > .text-chat-view, +.desktop-room-wrapper > .media-layout > .media-wrapper > .text-chat-view { + /* Account for height of .conversation-toolbar on desktop */ + /* When we change the toolbar in bug 1184559 we can remove this. */ + margin-top: 26px; + height: calc(100% - 150px - 26px); +} + /* Temporarily slaved from .media-wrapper until we use it in more places to avoid affecting the conversation window on desktop. */ .media-wrapper > .text-chat-view > .text-chat-entries { @@ -1204,7 +1187,7 @@ html[dir="rtl"] .room-context-btn-close { /* Temporarily slaved from .media-wrapper until we use it in more places to avoid affecting the conversation window on desktop. */ - .media-wrapper > .text-chat-view > .text-chat-entries { + .text-chat-view > .text-chat-entries { /* 40px is the height of .text-chat-box. */ height: calc(100% - 40px); width: 100%; @@ -1215,20 +1198,26 @@ html[dir="rtl"] .room-context-btn-close { height: 100%; } - .media-wrapper > .local { + .media-wrapper > .focus-stream > .local { /* Position over the remote video */ position: absolute; /* Make sure its on top */ - z-index: 1001; + z-index: 2; margin: 3px; right: 0; /* 29px is (30% of 50px high header) + (height toolbar (38px) + height footer (25px) - height header (50px)) */ - bottom: calc(30% + 29px); + bottom: 0; width: 120px; height: 120px; } + .standalone-room-wrapper > .media-layout > .media-wrapper > .local { + /* Add 10px for the margin on standalone */ + right: 10px; + } + + html[dir="rtl"] .media-wrapper > .local { right: auto; left: 0; @@ -1247,6 +1236,15 @@ html[dir="rtl"] .room-context-btn-close { height: 30%; } + .desktop-call-wrapper > .media-layout > .media-wrapper > .text-chat-view, + .desktop-room-wrapper > .media-layout > .media-wrapper > .text-chat-view { + /* When we change the toolbar in bug 1184559 we can remove this. */ + /* Reset back to 0 for .conversation-toolbar override on desktop */ + margin-top: 0; + /* This is temp, to echo the .media-wrapper > .text-chat-view above */ + height: 30%; + } + .media-wrapper.receiving-screen-share > .screen { order: 1; } @@ -1288,6 +1286,47 @@ html[dir="rtl"] .room-context-btn-close { } } +/* e.g. very narrow widths similar to conversation window */ +@media screen and (max-width:300px) { + .media-layout > .media-wrapper { + flex-flow: column nowrap; + } + + .media-wrapper > .focus-stream > .local { + position: absolute; + right: 0; + /* 30% is the height of the text chat. As we have a margin, + we don't need to worry about any offset for a border */ + bottom: 0; + margin: 3px; + object-fit: contain; + /* These make the avatar look reasonable and the local + video not too big */ + width: 25%; + height: 25%; + } + + .media-wrapper:not(.showing-remote-streams) > .focus-stream > .no-video { + display: none; + } + + .media-wrapper:not(.showing-remote-streams) > .focus-stream > .local { + position: relative; + margin: 0; + right: auto; + left: auto; + bottom: auto; + width: 100%; + height: 100%; + background-color: black; + } + + .media-wrapper > .focus-stream { + flex: 1 1 auto; + height: auto; + } +} + .standalone > #main > .room-conversation-wrapper > .media-layout > .conversation-toolbar { border: none; } @@ -1415,37 +1454,12 @@ html[dir="rtl"] .standalone .room-conversation-wrapper .room-inner-info-area { height: auto; } -/* Text chat in rooms styles */ - -.fx-embedded .room-conversation-wrapper { - display: flex; - flex-flow: column nowrap; -} - -.fx-embedded .video-layout-wrapper { - flex: 1 1 auto; -} +/* Text chat in styles */ .text-chat-view { background: white; } -.fx-embedded .text-chat-view { - flex: 1 0 auto; - display: flex; - flex-flow: column nowrap; -} - -.fx-embedded .text-chat-entries { - flex: 1 1 auto; - max-height: 120px; - min-height: 60px; -} - -.fx-embedded .text-chat-view > .text-chat-entries-empty { - display: none; -} - .text-chat-box { flex: 0 0 auto; max-height: 40px; @@ -1740,6 +1754,47 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow { } } +/* e.g. very narrow widths similar to conversation window */ +@media screen and (max-width:300px) { + .text-chat-view { + flex: 0 0 auto; + display: flex; + flex-flow: column nowrap; + /* 120px max-height of .text-chat-entries plus 40px of .text-chat-box */ + max-height: 160px; + /* 60px min-height of .text-chat-entries plus 40px of .text-chat-box */ + min-height: 100px; + /* The !important is to override the values defined above which have more + specificity when we fix bug 1184559, we should be able to remove it, + but this should be tests first. */ + height: auto !important; + } + + .text-chat-entries { + /* The !important is to override the values defined above which have more + specificity when we fix bug 1184559, we should be able to remove it, + but this should be tests first. */ + flex: 1 1 auto !important; + max-height: 120px; + min-height: 60px; + } + + .text-chat-entries-empty.text-chat-disabled { + display: none; + } + + /* When the text chat entries are not present, then hide the entries view + and just show the chat box. */ + .text-chat-entries-empty { + max-height: 40px; + min-height: 40px; + } + + .text-chat-entries-empty > .text-chat-entries { + display: none; + } +} + .self-view-hidden-message { /* Not displayed by default; display is turned on elsewhere when the * self-view is actually hidden. diff --git a/browser/components/loop/content/shared/js/activeRoomStore.js b/browser/components/loop/content/shared/js/activeRoomStore.js index 62eb8bbd339..835c64ee709 100644 --- a/browser/components/loop/content/shared/js/activeRoomStore.js +++ b/browser/components/loop/content/shared/js/activeRoomStore.js @@ -580,21 +580,6 @@ loop.store.ActiveRoomStore = (function() { * @param {sharedActions.ConnectionFailure} actionData */ connectionFailure: function(actionData) { - /** - * XXX This is a workaround for desktop machines that do not have a - * camera installed. As we don't yet have device enumeration, when - * we do, this can be removed (bug 1138851), and the sdk should handle it. - */ - if (this._isDesktop && - actionData.reason === FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA && - this.getStoreState().videoMuted === false) { - // We failed to publish with media, so due to the bug, we try again without - // video. - this.setStoreState({videoMuted: true}); - this._sdkDriver.retryPublishWithoutVideo(); - return; - } - var exitState = this._storeState.roomState === ROOM_STATES.FAILED ? this._storeState.failureExitState : this._storeState.roomState; diff --git a/browser/components/loop/content/shared/js/conversationStore.js b/browser/components/loop/content/shared/js/conversationStore.js index 211972c055b..6d99673b184 100644 --- a/browser/components/loop/content/shared/js/conversationStore.js +++ b/browser/components/loop/content/shared/js/conversationStore.js @@ -146,21 +146,6 @@ loop.store = loop.store || {}; * @param {sharedActions.ConnectionFailure} actionData The action data. */ connectionFailure: function(actionData) { - /** - * XXX This is a workaround for desktop machines that do not have a - * camera installed. As we don't yet have device enumeration, when - * we do, this can be removed (bug 1138851), and the sdk should handle it. - */ - if (this._isDesktop && - actionData.reason === FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA && - this.getStoreState().videoMuted === false) { - // We failed to publish with media, so due to the bug, we try again without - // video. - this.setStoreState({videoMuted: true}); - this.sdkDriver.retryPublishWithoutVideo(); - return; - } - this._endSession(); this.setStoreState({ callState: CALL_STATES.TERMINATED, diff --git a/browser/components/loop/content/shared/js/otSdkDriver.js b/browser/components/loop/content/shared/js/otSdkDriver.js index 994d2e2ab13..9b337dd70fd 100644 --- a/browser/components/loop/content/shared/js/otSdkDriver.js +++ b/browser/components/loop/content/shared/js/otSdkDriver.js @@ -61,15 +61,26 @@ loop.OTSdkDriver = (function() { /** * XXX This is a workaround for desktop machines that do not have a - * camera installed. As we don't yet have device enumeration, when - * we do, this can be removed (bug 1138851), and the sdk should handle it. + * camera installed. The SDK doesn't currently do use the new device + * enumeration apis, when it does (bug 1138851), we can drop this part. */ - if (this._isDesktop && !window.MediaStreamTrack.getSources) { + if (this._isDesktop) { // If there's no getSources function, the sdk defines its own and caches - // the result. So here we define the "normal" one which doesn't get cached, so - // we can change it later. + // the result. So here we define our own one which wraps around the + // real device enumeration api. window.MediaStreamTrack.getSources = function(callback) { - callback([{kind: "audio"}, {kind: "video"}]); + navigator.mediaDevices.enumerateDevices().then(function(devices) { + var result = []; + devices.forEach(function(device) { + if (device.kind === "audioinput") { + result.push({kind: "audio"}); + } + if (device.kind === "videoinput") { + result.push({kind: "video"}); + } + }); + callback(result); + }); }; } }; @@ -109,21 +120,13 @@ loop.OTSdkDriver = (function() { this.sdk.on("exception", this._onOTException.bind(this)); - // At this state we init the publisher, even though we might be waiting for - // the initial connect of the session. This saves time when setting up - // the media. - this._publishLocalStreams(); - }, - - /** - * Internal function to publish a local stream. - * XXX This can be simplified when bug 1138851 is actioned. - */ - _publishLocalStreams: function() { // We expect the local video to be muted automatically by the SDK. Hence // we don't mute it manually here. this._mockPublisherEl = document.createElement("div"); + // At this state we init the publisher, even though we might be waiting for + // the initial connect of the session. This saves time when setting up + // the media. this.publisher = this.sdk.initPublisher(this._mockPublisherEl, _.extend(this._getDataChannelSettings, this._getCopyPublisherConfig)); @@ -135,17 +138,6 @@ loop.OTSdkDriver = (function() { this._onAccessDialogOpened.bind(this)); }, - /** - * Forces the sdk into not using video, and starts publishing again. - * XXX This is part of the work around that will be removed by bug 1138851. - */ - retryPublishWithoutVideo: function() { - window.MediaStreamTrack.getSources = function(callback) { - callback([{kind: "audio"}]); - }; - this._publishLocalStreams(); - }, - /** * Handles the setMute action. Informs the published stream to mute * or unmute audio as appropriate. diff --git a/browser/components/loop/content/shared/js/textChatView.js b/browser/components/loop/content/shared/js/textChatView.js index caae7b25ff1..c24ebbfd7bf 100644 --- a/browser/components/loop/content/shared/js/textChatView.js +++ b/browser/components/loop/content/shared/js/textChatView.js @@ -150,8 +150,7 @@ loop.shared.views.chat = (function(mozL10n) { var lastTimestamp = 0; var entriesClasses = React.addons.classSet({ - "text-chat-entries": true, - "text-chat-entries-empty": !this.props.messageList.length + "text-chat-entries": true }); return ( @@ -382,7 +381,8 @@ loop.shared.views.chat = (function(mozL10n) { var textChatViewClasses = React.addons.classSet({ "text-chat-view": true, - "text-chat-disabled": !this.state.textChatEnabled + "text-chat-disabled": !this.state.textChatEnabled, + "text-chat-entries-empty": !messageList.length }); return ( diff --git a/browser/components/loop/content/shared/js/textChatView.jsx b/browser/components/loop/content/shared/js/textChatView.jsx index ed6159e29a0..e9ad31f02be 100644 --- a/browser/components/loop/content/shared/js/textChatView.jsx +++ b/browser/components/loop/content/shared/js/textChatView.jsx @@ -150,8 +150,7 @@ loop.shared.views.chat = (function(mozL10n) { var lastTimestamp = 0; var entriesClasses = React.addons.classSet({ - "text-chat-entries": true, - "text-chat-entries-empty": !this.props.messageList.length + "text-chat-entries": true }); return ( @@ -382,7 +381,8 @@ loop.shared.views.chat = (function(mozL10n) { var textChatViewClasses = React.addons.classSet({ "text-chat-view": true, - "text-chat-disabled": !this.state.textChatEnabled + "text-chat-disabled": !this.state.textChatEnabled, + "text-chat-entries-empty": !messageList.length }); return ( diff --git a/browser/components/loop/content/shared/js/views.js b/browser/components/loop/content/shared/js/views.js index 4384485bbcc..c0ba7fe031e 100644 --- a/browser/components/loop/content/shared/js/views.js +++ b/browser/components/loop/content/shared/js/views.js @@ -946,6 +946,7 @@ loop.shared.views = (function(_, mozL10n) { var MediaLayoutView = React.createClass({displayName: "MediaLayoutView", propTypes: { + children: React.PropTypes.node, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, displayScreenShare: React.PropTypes.bool.isRequired, isLocalLoading: React.PropTypes.bool.isRequired, @@ -955,6 +956,9 @@ loop.shared.views = (function(_, mozL10n) { localPosterUrl: React.PropTypes.string, localSrcVideoObject: React.PropTypes.object, localVideoMuted: React.PropTypes.bool.isRequired, + // Passing in matchMedia, allows it to be overriden for ui-showcase's + // benefit. We expect either the override or window.matchMedia. + matchMedia: React.PropTypes.func.isRequired, remotePosterUrl: React.PropTypes.string, remoteSrcVideoObject: React.PropTypes.object, renderRemoteVideo: React.PropTypes.bool.isRequired, @@ -964,6 +968,60 @@ loop.shared.views = (function(_, mozL10n) { useDesktopPaths: React.PropTypes.bool.isRequired }, + isLocalMediaAbsolutelyPositioned: function(matchMedia) { + if (!matchMedia) { + matchMedia = this.props.matchMedia; + } + return matchMedia && + // The screen width is less than 640px and we are not screen sharing. + ((matchMedia("screen and (max-width:640px)").matches && + !this.props.displayScreenShare) || + // or the screen width is less than 300px. + (matchMedia("screen and (max-width:300px)").matches)); + }, + + getInitialState: function() { + return { + localMediaAboslutelyPositioned: this.isLocalMediaAbsolutelyPositioned() + }; + }, + + componentWillReceiveProps: function(nextProps) { + // This is all for the ui-showcase's benefit. + if (this.props.matchMedia != nextProps.matchMedia) { + this.updateLocalMediaState(null, nextProps.matchMedia); + } + }, + + componentDidMount: function() { + window.addEventListener("resize", this.updateLocalMediaState); + }, + + componentWillUnmount: function() { + window.removeEventListener("resize", this.updateLocalMediaState); + }, + + updateLocalMediaState: function(event, matchMedia) { + var newState = this.isLocalMediaAbsolutelyPositioned(matchMedia); + if (this.state.localMediaAboslutelyPositioned != newState) { + this.setState({ + localMediaAboslutelyPositioned: newState + }); + } + }, + + renderLocalVideo: function() { + return ( + React.createElement("div", {className: "local"}, + React.createElement(MediaView, {displayAvatar: this.props.localVideoMuted, + isLoading: this.props.isLocalLoading, + mediaType: "local", + posterUrl: this.props.localPosterUrl, + srcVideoObject: this.props.localSrcVideoObject}) + ) + ); + }, + render: function() { var remoteStreamClasses = React.addons.classSet({ "remote": true, @@ -979,7 +1037,9 @@ loop.shared.views = (function(_, mozL10n) { "media-wrapper": true, "receiving-screen-share": this.props.displayScreenShare, "showing-local-streams": this.props.localSrcVideoObject || - this.props.localPosterUrl + this.props.localPosterUrl, + "showing-remote-streams": this.props.remoteSrcVideoObject || + this.props.remotePosterUrl || this.props.isRemoteLoading }); return ( @@ -993,7 +1053,10 @@ loop.shared.views = (function(_, mozL10n) { isLoading: this.props.isRemoteLoading, mediaType: "remote", posterUrl: this.props.remotePosterUrl, - srcVideoObject: this.props.remoteSrcVideoObject}) + srcVideoObject: this.props.remoteSrcVideoObject}), + this.state.localMediaAboslutelyPositioned ? + this.renderLocalVideo() : null, + this.props.children ), React.createElement("div", {className: screenShareStreamClasses}, React.createElement(MediaView, {displayAvatar: false, @@ -1006,13 +1069,8 @@ loop.shared.views = (function(_, mozL10n) { dispatcher: this.props.dispatcher, showRoomName: this.props.showContextRoomName, useDesktopPaths: false}), - React.createElement("div", {className: "local"}, - React.createElement(MediaView, {displayAvatar: this.props.localVideoMuted, - isLoading: this.props.isLocalLoading, - mediaType: "local", - posterUrl: this.props.localPosterUrl, - srcVideoObject: this.props.localSrcVideoObject}) - ) + this.state.localMediaAboslutelyPositioned ? + null : this.renderLocalVideo() ) ) ); diff --git a/browser/components/loop/content/shared/js/views.jsx b/browser/components/loop/content/shared/js/views.jsx index 48442014ed3..efec9f4ddfb 100644 --- a/browser/components/loop/content/shared/js/views.jsx +++ b/browser/components/loop/content/shared/js/views.jsx @@ -946,6 +946,7 @@ loop.shared.views = (function(_, mozL10n) { var MediaLayoutView = React.createClass({ propTypes: { + children: React.PropTypes.node, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, displayScreenShare: React.PropTypes.bool.isRequired, isLocalLoading: React.PropTypes.bool.isRequired, @@ -955,6 +956,9 @@ loop.shared.views = (function(_, mozL10n) { localPosterUrl: React.PropTypes.string, localSrcVideoObject: React.PropTypes.object, localVideoMuted: React.PropTypes.bool.isRequired, + // Passing in matchMedia, allows it to be overriden for ui-showcase's + // benefit. We expect either the override or window.matchMedia. + matchMedia: React.PropTypes.func.isRequired, remotePosterUrl: React.PropTypes.string, remoteSrcVideoObject: React.PropTypes.object, renderRemoteVideo: React.PropTypes.bool.isRequired, @@ -964,6 +968,60 @@ loop.shared.views = (function(_, mozL10n) { useDesktopPaths: React.PropTypes.bool.isRequired }, + isLocalMediaAbsolutelyPositioned: function(matchMedia) { + if (!matchMedia) { + matchMedia = this.props.matchMedia; + } + return matchMedia && + // The screen width is less than 640px and we are not screen sharing. + ((matchMedia("screen and (max-width:640px)").matches && + !this.props.displayScreenShare) || + // or the screen width is less than 300px. + (matchMedia("screen and (max-width:300px)").matches)); + }, + + getInitialState: function() { + return { + localMediaAboslutelyPositioned: this.isLocalMediaAbsolutelyPositioned() + }; + }, + + componentWillReceiveProps: function(nextProps) { + // This is all for the ui-showcase's benefit. + if (this.props.matchMedia != nextProps.matchMedia) { + this.updateLocalMediaState(null, nextProps.matchMedia); + } + }, + + componentDidMount: function() { + window.addEventListener("resize", this.updateLocalMediaState); + }, + + componentWillUnmount: function() { + window.removeEventListener("resize", this.updateLocalMediaState); + }, + + updateLocalMediaState: function(event, matchMedia) { + var newState = this.isLocalMediaAbsolutelyPositioned(matchMedia); + if (this.state.localMediaAboslutelyPositioned != newState) { + this.setState({ + localMediaAboslutelyPositioned: newState + }); + } + }, + + renderLocalVideo: function() { + return ( +
+ +
+ ); + }, + render: function() { var remoteStreamClasses = React.addons.classSet({ "remote": true, @@ -979,7 +1037,9 @@ loop.shared.views = (function(_, mozL10n) { "media-wrapper": true, "receiving-screen-share": this.props.displayScreenShare, "showing-local-streams": this.props.localSrcVideoObject || - this.props.localPosterUrl + this.props.localPosterUrl, + "showing-remote-streams": this.props.remoteSrcVideoObject || + this.props.remotePosterUrl || this.props.isRemoteLoading }); return ( @@ -994,6 +1054,9 @@ loop.shared.views = (function(_, mozL10n) { mediaType="remote" posterUrl={this.props.remotePosterUrl} srcVideoObject={this.props.remoteSrcVideoObject} /> + { this.state.localMediaAboslutelyPositioned ? + this.renderLocalVideo() : null } + { this.props.children }
-
- -
+ { this.state.localMediaAboslutelyPositioned ? + null : this.renderLocalVideo() }
); diff --git a/browser/components/loop/standalone/content/js/standaloneRoomViews.js b/browser/components/loop/standalone/content/js/standaloneRoomViews.js index 746bb8413a3..8ed26cef79c 100644 --- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js +++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js @@ -256,11 +256,12 @@ loop.standaloneRoomViews = (function(mozL10n) { mixins: [ Backbone.Events, sharedMixins.MediaSetupMixin, - sharedMixins.RoomsAudioMixin, - loop.store.StoreMixin("activeRoomStore") + sharedMixins.RoomsAudioMixin ], propTypes: { + // We pass conversationStore here rather than use the mixin, to allow + // easy configurability for the ui-showcase. activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) @@ -282,6 +283,16 @@ loop.standaloneRoomViews = (function(mozL10n) { }); }, + componentWillMount: function() { + this.props.activeRoomStore.on("change", function() { + this.setState(this.props.activeRoomStore.getStoreState()); + }, this); + }, + + componentWillUnmount: function() { + this.props.activeRoomStore.off("change", null, this); + }, + componentDidMount: function() { // Adding a class to the document body element from here to ease styling it. document.body.classList.add("is-standalone-room"); @@ -429,7 +440,8 @@ loop.standaloneRoomViews = (function(mozL10n) { */ _isScreenShareLoading: function() { return this.state.receivingScreenShare && - !this.state.screenShareVideoObject; + !this.state.screenShareVideoObject && + !this.props.screenSharePosterUrl; }, render: function() { @@ -456,6 +468,7 @@ loop.standaloneRoomViews = (function(mozL10n) { localPosterUrl: this.props.localPosterUrl, localSrcVideoObject: this.state.localSrcVideoObject, localVideoMuted: this.state.videoMuted, + matchMedia: this.state.matchMedia || window.matchMedia.bind(window), remotePosterUrl: this.props.remotePosterUrl, remoteSrcVideoObject: this.state.remoteSrcVideoObject, renderRemoteVideo: this.shouldRenderRemoteVideo(), diff --git a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx index 02a78c95752..e798129e52e 100644 --- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx +++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx @@ -256,11 +256,12 @@ loop.standaloneRoomViews = (function(mozL10n) { mixins: [ Backbone.Events, sharedMixins.MediaSetupMixin, - sharedMixins.RoomsAudioMixin, - loop.store.StoreMixin("activeRoomStore") + sharedMixins.RoomsAudioMixin ], propTypes: { + // We pass conversationStore here rather than use the mixin, to allow + // easy configurability for the ui-showcase. activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) @@ -282,6 +283,16 @@ loop.standaloneRoomViews = (function(mozL10n) { }); }, + componentWillMount: function() { + this.props.activeRoomStore.on("change", function() { + this.setState(this.props.activeRoomStore.getStoreState()); + }, this); + }, + + componentWillUnmount: function() { + this.props.activeRoomStore.off("change", null, this); + }, + componentDidMount: function() { // Adding a class to the document body element from here to ease styling it. document.body.classList.add("is-standalone-room"); @@ -429,7 +440,8 @@ loop.standaloneRoomViews = (function(mozL10n) { */ _isScreenShareLoading: function() { return this.state.receivingScreenShare && - !this.state.screenShareVideoObject; + !this.state.screenShareVideoObject && + !this.props.screenSharePosterUrl; }, render: function() { @@ -456,6 +468,7 @@ loop.standaloneRoomViews = (function(mozL10n) { localPosterUrl={this.props.localPosterUrl} localSrcVideoObject={this.state.localSrcVideoObject} localVideoMuted={this.state.videoMuted} + matchMedia={this.state.matchMedia || window.matchMedia.bind(window)} remotePosterUrl={this.props.remotePosterUrl} remoteSrcVideoObject={this.state.remoteSrcVideoObject} renderRemoteVideo={this.shouldRenderRemoteVideo()} diff --git a/browser/components/loop/test/desktop-local/conversationViews_test.js b/browser/components/loop/test/desktop-local/conversationViews_test.js index b17caf21951..08b6da245c5 100644 --- a/browser/components/loop/test/desktop-local/conversationViews_test.js +++ b/browser/components/loop/test/desktop-local/conversationViews_test.js @@ -474,7 +474,9 @@ describe("loop.conversationViews", function () { describe("OngoingConversationView", function() { function mountTestComponent(extraProps) { var props = _.extend({ - dispatcher: dispatcher + conversationStore: conversationStore, + dispatcher: dispatcher, + matchMedia: window.matchMedia }, extraProps); return TestUtils.renderIntoDocument( React.createElement(loop.conversationViews.OngoingConversationView, props)); @@ -489,15 +491,6 @@ describe("loop.conversationViews", function () { sinon.match.hasOwn("name", "setupStreamElements")); }); - it("should display an avatar for remote video when the stream is not enabled", function() { - view = mountTestComponent({ - mediaConnected: true, - remoteVideoEnabled: false - }); - - TestUtils.findRenderedComponentWithType(view, sharedViews.AvatarView); - }); - it("should display the remote video when the stream is enabled", function() { conversationStore.setStoreState({ remoteSrcVideoObject: { fake: 1 } @@ -511,16 +504,6 @@ describe("loop.conversationViews", function () { expect(view.getDOMNode().querySelector(".remote video")).not.eql(null); }); - it("should display an avatar for local video when the stream is not enabled", function() { - view = mountTestComponent({ - video: { - enabled: false - } - }); - - TestUtils.findRenderedComponentWithType(view, sharedViews.AvatarView); - }); - it("should display the local video when the stream is enabled", function() { conversationStore.setStoreState({ localSrcVideoObject: { fake: 1 } diff --git a/browser/components/loop/test/desktop-local/index.html b/browser/components/loop/test/desktop-local/index.html index d74b99791a9..4f30c2cfd3a 100644 --- a/browser/components/loop/test/desktop-local/index.html +++ b/browser/components/loop/test/desktop-local/index.html @@ -95,7 +95,7 @@ describe("Unexpected Warnings Check", function() { it("should long only the warnings we expect", function() { - chai.expect(caughtWarnings.length).to.eql(27); + chai.expect(caughtWarnings.length).to.eql(28); }); }); diff --git a/browser/components/loop/test/desktop-local/roomViews_test.js b/browser/components/loop/test/desktop-local/roomViews_test.js index 961deb305ba..fe02d07a032 100644 --- a/browser/components/loop/test/desktop-local/roomViews_test.js +++ b/browser/components/loop/test/desktop-local/roomViews_test.js @@ -598,21 +598,6 @@ describe("loop.roomViews", function () { }); - describe("Mute", function() { - it("should render local media as audio-only if video is muted", - function() { - activeRoomStore.setStoreState({ - roomState: ROOM_STATES.SESSION_CONNECTED, - videoMuted: true - }); - - view = mountTestComponent(); - - expect(view.getDOMNode().querySelector(".local-stream-audio")) - .not.eql(null); - }); - }); - describe("Edit Context", function() { it("should show the form when the edit button is clicked", function() { view = mountTestComponent(); diff --git a/browser/components/loop/test/functional/test_1_browser_call.py b/browser/components/loop/test/functional/test_1_browser_call.py index 3c9c5d0d218..836d9aeb3c3 100644 --- a/browser/components/loop/test/functional/test_1_browser_call.py +++ b/browser/components/loop/test/functional/test_1_browser_call.py @@ -99,7 +99,7 @@ class Test1BrowserCall(MarionetteTestCase): self.switch_to_chatbox() # expect a video container on desktop side - media_container = self.wait_for_element_displayed(By.CLASS_NAME, "media") + media_container = self.wait_for_element_displayed(By.CLASS_NAME, "media-layout") self.assertEqual(media_container.tag_name, "div", "expect a video container") self.check_video(".local-video") diff --git a/browser/components/loop/test/mochitest/.eslintrc b/browser/components/loop/test/mochitest/.eslintrc index 7a196541186..5833aeeb7f8 100644 --- a/browser/components/loop/test/mochitest/.eslintrc +++ b/browser/components/loop/test/mochitest/.eslintrc @@ -21,6 +21,7 @@ "gMozLoopAPI": true, "mockDb": true, "mockPushHandler": true, + "OpenBrowserWindow": true, "promiseDeletedOAuthParams": false, "promiseOAuthGetRegistration": false, "promiseOAuthParamsSetup": false, diff --git a/browser/components/loop/test/mochitest/browser_toolbarbutton.js b/browser/components/loop/test/mochitest/browser_toolbarbutton.js index 95b8ed32560..1bb2285c12d 100644 --- a/browser/components/loop/test/mochitest/browser_toolbarbutton.js +++ b/browser/components/loop/test/mochitest/browser_toolbarbutton.js @@ -167,3 +167,19 @@ add_task(function* test_screen_share() { MozLoopService.setScreenShareState("1", false); Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state"); }); + +add_task(function* test_private_browsing_window() { + let win = OpenBrowserWindow({ private: true }); + yield new Promise(resolve => { + win.addEventListener("load", function listener() { + win.removeEventListener("load", listener); + resolve(); + }); + }); + + let button = win.LoopUI.toolbarButton.node; + Assert.ok(button, "Loop button should be present"); + Assert.ok(button.getAttribute("disabled"), "Disabled attribute should be set"); + + win.close(); +}); diff --git a/browser/components/loop/test/shared/activeRoomStore_test.js b/browser/components/loop/test/shared/activeRoomStore_test.js index 1b8d11d7cfd..55f7bb96b3a 100644 --- a/browser/components/loop/test/shared/activeRoomStore_test.js +++ b/browser/components/loop/test/shared/activeRoomStore_test.js @@ -916,26 +916,6 @@ describe("loop.store.ActiveRoomStore", function () { }); }); - it("should retry publishing if on desktop, and in the videoMuted state", function() { - store._isDesktop = true; - - store.connectionFailure(new sharedActions.ConnectionFailure({ - reason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA - })); - - sinon.assert.calledOnce(fakeSdkDriver.retryPublishWithoutVideo); - }); - - it("should set videoMuted to try when retrying publishing", function() { - store._isDesktop = true; - - store.connectionFailure(new sharedActions.ConnectionFailure({ - reason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA - })); - - expect(store.getStoreState().videoMuted).eql(true); - }); - it("should store the failure reason", function() { store.connectionFailure(connectionFailureAction); diff --git a/browser/components/loop/test/shared/conversationStore_test.js b/browser/components/loop/test/shared/conversationStore_test.js index d696e784970..f8dbbc9a9f7 100644 --- a/browser/components/loop/test/shared/conversationStore_test.js +++ b/browser/components/loop/test/shared/conversationStore_test.js @@ -147,26 +147,6 @@ describe("loop.store.ConversationStore", function () { store.setStoreState({windowId: "42"}); }); - it("should retry publishing if on desktop, and in the videoMuted state", function() { - store._isDesktop = true; - - store.connectionFailure(new sharedActions.ConnectionFailure({ - reason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA - })); - - sinon.assert.calledOnce(sdkDriver.retryPublishWithoutVideo); - }); - - it("should set videoMuted to try when retrying publishing", function() { - store._isDesktop = true; - - store.connectionFailure(new sharedActions.ConnectionFailure({ - reason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA - })); - - expect(store.getStoreState().videoMuted).eql(true); - }); - it("should disconnect the session", function() { store.connectionFailure( new sharedActions.ConnectionFailure({reason: "fake"})); diff --git a/browser/components/loop/test/shared/otSdkDriver_test.js b/browser/components/loop/test/shared/otSdkDriver_test.js index 0706e83edd8..c31febdc2fd 100644 --- a/browser/components/loop/test/shared/otSdkDriver_test.js +++ b/browser/components/loop/test/shared/otSdkDriver_test.js @@ -133,43 +133,6 @@ describe("loop.OTSdkDriver", function () { }); }); - describe("#retryPublishWithoutVideo", function() { - beforeEach(function() { - sdk.initPublisher.returns(publisher); - - driver.setupStreamElements(new sharedActions.SetupStreamElements({ - publisherConfig: publisherConfig - })); - }); - - it("should make MediaStreamTrack.getSources return without a video source", function(done) { - driver.retryPublishWithoutVideo(); - - window.MediaStreamTrack.getSources(function(sources) { - expect(sources.some(function(src) { - return src.kind === "video"; - })).eql(false); - - done(); - }); - }); - - it("should call initPublisher", function() { - driver.retryPublishWithoutVideo(); - - var expectedConfig = _.extend({ - channels: { - text: {} - } - }, publisherConfig); - - sinon.assert.calledTwice(sdk.initPublisher); - sinon.assert.calledWith(sdk.initPublisher, - sinon.match.instanceOf(HTMLDivElement), - expectedConfig); - }); - }); - describe("#setMute", function() { beforeEach(function() { sdk.initPublisher.returns(publisher); diff --git a/browser/components/loop/test/shared/textChatView_test.js b/browser/components/loop/test/shared/textChatView_test.js index b3a70f76ad3..031db17b658 100644 --- a/browser/components/loop/test/shared/textChatView_test.js +++ b/browser/components/loop/test/shared/textChatView_test.js @@ -56,27 +56,6 @@ describe("loop.shared.views.TextChatView", function () { store.setStoreState({ textChatEnabled: true }); }); - it("should add an empty class when the list is empty", function() { - view = mountTestComponent({ - messageList: [] - }); - - expect(view.getDOMNode().classList.contains("text-chat-entries-empty")).eql(true); - }); - - it("should not add an empty class when the list is has items", function() { - view = mountTestComponent({ - messageList: [{ - type: CHAT_MESSAGE_TYPES.RECEIVED, - contentType: CHAT_CONTENT_TYPES.TEXT, - message: "Hello!", - receivedTimestamp: "2015-06-25T17:53:55.357Z" - }] - }); - - expect(view.getDOMNode().classList.contains("text-chat-entries-empty")).eql(false); - }); - it("should render message entries when message were sent/ received", function() { view = mountTestComponent({ messageList: [{ @@ -297,6 +276,41 @@ describe("loop.shared.views.TextChatView", function () { fakeServer.restore(); }); + it("should add a disabled class when text chat is disabled", function() { + view = mountTestComponent(); + + store.setStoreState({ textChatEnabled: false }); + + expect(view.getDOMNode().classList.contains("text-chat-disabled")).eql(true); + }); + + it("should not a disabled class when text chat is enabled", function() { + view = mountTestComponent(); + + store.setStoreState({ textChatEnabled: true }); + + expect(view.getDOMNode().classList.contains("text-chat-disabled")).eql(false); + }); + + it("should add an empty class when the entries list is empty", function() { + view = mountTestComponent(); + + expect(view.getDOMNode().classList.contains("text-chat-entries-empty")).eql(true); + }); + + it("should not add an empty class when the entries list is has items", function() { + view = mountTestComponent(); + + store.sendTextChatMessage({ + contentType: CHAT_CONTENT_TYPES.TEXT, + message: "Hello!", + sentTimestamp: "1970-01-01T00:02:00.000Z", + receivedTimestamp: "1970-01-01T00:02:00.000Z" + }); + + expect(view.getDOMNode().classList.contains("text-chat-entries-empty")).eql(false); + }); + it("should show timestamps from msgs sent more than 1 min apart", function() { view = mountTestComponent(); @@ -326,12 +340,6 @@ describe("loop.shared.views.TextChatView", function () { .to.eql(2); }); - it("should display the view if no messages and text chat is enabled", function() { - view = mountTestComponent(); - - expect(view.getDOMNode()).not.eql(null); - }); - it("should render message entries when message were sent/ received", function() { view = mountTestComponent(); diff --git a/browser/components/loop/test/shared/views_test.js b/browser/components/loop/test/shared/views_test.js index 546a586d0b9..67d282e9e29 100644 --- a/browser/components/loop/test/shared/views_test.js +++ b/browser/components/loop/test/shared/views_test.js @@ -1057,6 +1057,7 @@ describe("loop.shared.views", function() { isRemoteLoading: false, isScreenShareLoading: false, localVideoMuted: false, + matchMedia: window.matchMedia, renderRemoteVideo: false, showContextRoomName: false, useDesktopPaths: false @@ -1144,5 +1145,35 @@ describe("loop.shared.views", function() { expect(view.getDOMNode().querySelector(".media-wrapper") .classList.contains("showing-local-streams")).eql(true); }); + + it("should not mark the wrapper as showing remote streams when not displaying a stream", function() { + view = mountTestComponent({ + remoteSrcVideoObject: null, + remotePosterUrl: null + }); + + expect(view.getDOMNode().querySelector(".media-wrapper") + .classList.contains("showing-remote-streams")).eql(false); + }); + + it("should mark the wrapper as showing remote streams when displaying a stream", function() { + view = mountTestComponent({ + remoteSrcVideoObject: {}, + remotePosterUrl: null + }); + + expect(view.getDOMNode().querySelector(".media-wrapper") + .classList.contains("showing-remote-streams")).eql(true); + }); + + it("should mark the wrapper as showing remote streams when displaying a poster url", function() { + view = mountTestComponent({ + remoteSrcVideoObject: {}, + remotePosterUrl: "fake/url" + }); + + expect(view.getDOMNode().querySelector(".media-wrapper") + .classList.contains("showing-remote-streams")).eql(true); + }); }); }); diff --git a/browser/components/loop/ui/ui-showcase.js b/browser/components/loop/ui/ui-showcase.js index b07d76312c5..3bb456a7634 100644 --- a/browser/components/loop/ui/ui-showcase.js +++ b/browser/components/loop/ui/ui-showcase.js @@ -75,13 +75,25 @@ var dispatcher = new loop.Dispatcher(); - var mockSDK = _.extend({ + var MockSDK = function() { + dispatcher.register(this, [ + "setupStreamElements" + ]); + }; + + MockSDK.prototype = { + setupStreamElements: function() { + // Dummy function to stop warnings. + }, + sendTextChatMessage: function(message) { dispatcher.dispatch(new loop.shared.actions.ReceivedTextChatMessage({ message: message.message })); } - }, Backbone.Events); + }; + + var mockSDK = new MockSDK(); /** * Every view that uses an activeRoomStore needs its own; if they shared @@ -116,7 +128,6 @@ }); store.forcedUpdate = function forcedUpdate(contentWindow) { - // Since this is called by setTimeout, we don't want to lose any // exceptions if there's a problem and we need to debug, so... try { @@ -136,6 +147,17 @@ camera: {height: 480, orientation: 0, width: 640} }, remoteVideoEnabled: options.remoteVideoEnabled, + // Override the matchMedia, this is so that the correct version is + // used for the frame. + // + // Currently, we use an icky hack, and the showcase conspires with + // react-frame-component to set iframe.contentWindow.matchMedia onto + // the store. Once React context matures a bit (somewhere between + // 0.14 and 1.0, apparently): + // + // https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based + // + // we should be able to use those to clean this up. matchMedia: contentWindow.matchMedia.bind(contentWindow), roomState: options.roomState, videoMuted: !!options.videoMuted @@ -185,6 +207,10 @@ roomState: ROOM_STATES.HAS_PARTICIPANTS }); + var updatingMobileActiveRoomStore = makeActiveRoomStore({ + roomState: ROOM_STATES.HAS_PARTICIPANTS + }); + var localFaceMuteRoomStore = makeActiveRoomStore({ roomState: ROOM_STATES.HAS_PARTICIPANTS, videoMuted: true @@ -201,12 +227,19 @@ receivingScreenShare: true }); + var updatingSharingRoomMobileStore = makeActiveRoomStore({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + receivingScreenShare: true + }); + var loadingRemoteLoadingScreenStore = makeActiveRoomStore({ mediaConnected: false, + receivingScreenShare: true, roomState: ROOM_STATES.HAS_PARTICIPANTS, remoteSrcVideoObject: false }); var loadingScreenSharingRoomStore = makeActiveRoomStore({ + receivingScreenShare: true, roomState: ROOM_STATES.HAS_PARTICIPANTS }); @@ -234,7 +267,10 @@ }); var invitationRoomStore = new loop.store.RoomStore(dispatcher, { - mozLoop: navigator.mozLoop + mozLoop: navigator.mozLoop, + activeRoomStore: makeActiveRoomStore({ + roomState: ROOM_STATES.INIT + }) }); var roomStore = new loop.store.RoomStore(dispatcher, { @@ -253,6 +289,20 @@ }) }); + var desktopRoomStoreMedium = new loop.store.RoomStore(dispatcher, { + mozLoop: navigator.mozLoop, + activeRoomStore: makeActiveRoomStore({ + roomState: ROOM_STATES.HAS_PARTICIPANTS + }) + }); + + var desktopRoomStoreLarge = new loop.store.RoomStore(dispatcher, { + mozLoop: navigator.mozLoop, + activeRoomStore: makeActiveRoomStore({ + roomState: ROOM_STATES.HAS_PARTICIPANTS + }) + }); + var desktopLocalFaceMuteActiveRoomStore = makeActiveRoomStore({ roomState: ROOM_STATES.HAS_PARTICIPANTS, videoMuted: true @@ -272,15 +322,59 @@ activeRoomStore: desktopRemoteFaceMuteActiveRoomStore }); - var conversationStore = new loop.store.ConversationStore(dispatcher, { - client: {}, - mozLoop: navigator.mozLoop, - sdkDriver: mockSDK - }); var textChatStore = new loop.store.TextChatStore(dispatcher, { sdkDriver: mockSDK }); + /** + * Every view that uses an conversationStore needs its own; if they shared + * a conversation store, they'd interfere with each other. + * + * @param options + * @returns {loop.store.ConversationStore} + */ + function makeConversationStore() { + var roomDispatcher = new loop.Dispatcher(); + + var store = new loop.store.ConversationStore(dispatcher, { + client: {}, + mozLoop: navigator.mozLoop, + sdkDriver: mockSDK + }); + + store.forcedUpdate = function forcedUpdate(contentWindow) { + // Since this is called by setTimeout, we don't want to lose any + // exceptions if there's a problem and we need to debug, so... + try { + var newStoreState = { + // Override the matchMedia, this is so that the correct version is + // used for the frame. + // + // Currently, we use an icky hack, and the showcase conspires with + // react-frame-component to set iframe.contentWindow.matchMedia onto + // the store. Once React context matures a bit (somewhere between + // 0.14 and 1.0, apparently): + // + // https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based + // + // we should be able to use those to clean this up. + matchMedia: contentWindow.matchMedia.bind(contentWindow) + }; + + store.setStoreState(newStoreState); + } catch (ex) { + console.error("exception in forcedUpdate:", ex); + } + }; + + return store; + } + + var conversationStores = []; + for (var index = 0; index < 5; index++) { + conversationStores[index] = makeConversationStore(); + } + // Update the text chat store with the room info. textChatStore.updateRoomInfo(new sharedActions.UpdateRoomInfo({ roomName: "A Very Long Conversation Name", @@ -341,7 +435,7 @@ loop.store.StoreMixin.register({ activeRoomStore: activeRoomStore, - conversationStore: conversationStore, + conversationStore: conversationStores[0], textChatStore: textChatStore }); @@ -360,14 +454,6 @@ requestCallUrlInfo: noop }; - var mockConversationModel = new loop.shared.models.ConversationModel({ - callerId: "Mrs Jones", - urlCreationDate: (new Date() / 1000).toString() - }, { - sdk: mockSDK - }); - mockConversationModel.startSession = noop; - var mockWebSocket = new loop.CallConnectionWebSocket({ url: "fake", callId: "fakeId", @@ -763,7 +849,7 @@ React.createElement("div", {className: "fx-embedded"}, React.createElement(CallFailedView, {dispatcher: dispatcher, outgoing: false, - store: conversationStore}) + store: conversationStores[0]}) ) ), React.createElement(Example, {dashed: true, @@ -772,7 +858,7 @@ React.createElement("div", {className: "fx-embedded"}, React.createElement(CallFailedView, {dispatcher: dispatcher, outgoing: true, - store: conversationStore}) + store: conversationStores[1]}) ) ), React.createElement(Example, {dashed: true, @@ -781,18 +867,22 @@ React.createElement("div", {className: "fx-embedded"}, React.createElement(CallFailedView, {dispatcher: dispatcher, emailLinkError: true, outgoing: true, - store: conversationStore}) + store: conversationStores[0]}) ) ) ), React.createElement(Section, {name: "OngoingConversationView"}, - React.createElement(FramedExample, {height: 254, - summary: "Desktop ongoing conversation window", - width: 298}, + React.createElement(FramedExample, { + dashed: true, + height: 394, + onContentsRendered: conversationStores[0].forcedUpdate, + summary: "Desktop ongoing conversation window", + width: 298}, React.createElement("div", {className: "fx-embedded"}, React.createElement(OngoingConversationView, { audio: {enabled: true}, + conversationStore: conversationStores[0], dispatcher: dispatcher, localPosterUrl: "sample-img/video-screen-local.png", mediaConnected: true, @@ -802,28 +892,55 @@ ) ), - React.createElement(FramedExample, {height: 600, - summary: "Desktop ongoing conversation window large", - width: 800}, - React.createElement("div", {className: "fx-embedded"}, - React.createElement(OngoingConversationView, { - audio: {enabled: true}, - dispatcher: dispatcher, - localPosterUrl: "sample-img/video-screen-local.png", - mediaConnected: true, - remotePosterUrl: "sample-img/video-screen-remote.png", - remoteVideoEnabled: true, - video: {enabled: true}}) - ) + React.createElement(FramedExample, { + dashed: true, + height: 400, + onContentsRendered: conversationStores[1].forcedUpdate, + summary: "Desktop ongoing conversation window (medium)", + width: 600}, + React.createElement("div", {className: "fx-embedded"}, + React.createElement(OngoingConversationView, { + audio: {enabled: true}, + conversationStore: conversationStores[1], + dispatcher: dispatcher, + localPosterUrl: "sample-img/video-screen-local.png", + mediaConnected: true, + remotePosterUrl: "sample-img/video-screen-remote.png", + remoteVideoEnabled: true, + video: {enabled: true}}) + ) ), - React.createElement(FramedExample, {height: 254, + React.createElement(FramedExample, { + height: 600, + onContentsRendered: conversationStores[2].forcedUpdate, + summary: "Desktop ongoing conversation window (large)", + width: 800}, + React.createElement("div", {className: "fx-embedded"}, + React.createElement(OngoingConversationView, { + audio: {enabled: true}, + conversationStore: conversationStores[2], + dispatcher: dispatcher, + localPosterUrl: "sample-img/video-screen-local.png", + mediaConnected: true, + remotePosterUrl: "sample-img/video-screen-remote.png", + remoteVideoEnabled: true, + video: {enabled: true}}) + ) + ), + + React.createElement(FramedExample, { + dashed: true, + height: 394, + onContentsRendered: conversationStores[3].forcedUpdate, summary: "Desktop ongoing conversation window - local face mute", width: 298}, React.createElement("div", {className: "fx-embedded"}, React.createElement(OngoingConversationView, { audio: {enabled: true}, + conversationStore: conversationStores[3], dispatcher: dispatcher, + localPosterUrl: "sample-img/video-screen-local.png", mediaConnected: true, remotePosterUrl: "sample-img/video-screen-remote.png", remoteVideoEnabled: true, @@ -831,15 +948,19 @@ ) ), - React.createElement(FramedExample, {height: 254, + React.createElement(FramedExample, { + dashed: true, height: 394, + onContentsRendered: conversationStores[4].forcedUpdate, summary: "Desktop ongoing conversation window - remote face mute", width: 298}, React.createElement("div", {className: "fx-embedded"}, React.createElement(OngoingConversationView, { audio: {enabled: true}, + conversationStore: conversationStores[4], dispatcher: dispatcher, localPosterUrl: "sample-img/video-screen-local.png", mediaConnected: true, + remotePosterUrl: "sample-img/video-screen-remote.png", remoteVideoEnabled: false, video: {enabled: true}}) ) @@ -894,7 +1015,8 @@ React.createElement(Section, {name: "DesktopRoomConversationView"}, React.createElement(FramedExample, { - height: 254, + height: 398, + onContentsRendered: invitationRoomStore.activeRoomStore.forcedUpdate, summary: "Desktop room conversation (invitation, text-chat inclusion/scrollbars don't happen in real client)", width: 298}, React.createElement("div", {className: "fx-embedded"}, @@ -911,6 +1033,7 @@ React.createElement(FramedExample, { dashed: true, height: 394, + onContentsRendered: desktopRoomStoreLoading.activeRoomStore.forcedUpdate, summary: "Desktop room conversation (loading)", width: 298}, /* Hide scrollbars here. Rotating loading div overflows and causes @@ -927,8 +1050,12 @@ ) ), - React.createElement(FramedExample, {height: 254, - summary: "Desktop room conversation"}, + React.createElement(FramedExample, { + dashed: true, + height: 394, + onContentsRendered: roomStore.activeRoomStore.forcedUpdate, + summary: "Desktop room conversation", + width: 298}, React.createElement("div", {className: "fx-embedded"}, React.createElement(DesktopRoomConversationView, { dispatcher: dispatcher, @@ -941,10 +1068,48 @@ ) ), - React.createElement(FramedExample, {dashed: true, - height: 394, - summary: "Desktop room conversation local face-mute", - width: 298}, + React.createElement(FramedExample, { + dashed: true, + height: 482, + onContentsRendered: desktopRoomStoreMedium.activeRoomStore.forcedUpdate, + summary: "Desktop room conversation (medium)", + width: 602}, + React.createElement("div", {className: "fx-embedded"}, + React.createElement(DesktopRoomConversationView, { + dispatcher: dispatcher, + localPosterUrl: "sample-img/video-screen-local.png", + mozLoop: navigator.mozLoop, + onCallTerminated: function(){}, + remotePosterUrl: "sample-img/video-screen-remote.png", + roomState: ROOM_STATES.HAS_PARTICIPANTS, + roomStore: desktopRoomStoreMedium}) + ) + ), + + React.createElement(FramedExample, { + dashed: true, + height: 485, + onContentsRendered: desktopRoomStoreLarge.activeRoomStore.forcedUpdate, + summary: "Desktop room conversation (large)", + width: 646}, + React.createElement("div", {className: "fx-embedded"}, + React.createElement(DesktopRoomConversationView, { + dispatcher: dispatcher, + localPosterUrl: "sample-img/video-screen-local.png", + mozLoop: navigator.mozLoop, + onCallTerminated: function(){}, + remotePosterUrl: "sample-img/video-screen-remote.png", + roomState: ROOM_STATES.HAS_PARTICIPANTS, + roomStore: desktopRoomStoreLarge}) + ) + ), + + React.createElement(FramedExample, { + dashed: true, + height: 394, + onContentsRendered: desktopLocalFaceMuteRoomStore.activeRoomStore.forcedUpdate, + summary: "Desktop room conversation local face-mute", + width: 298}, React.createElement("div", {className: "fx-embedded"}, React.createElement(DesktopRoomConversationView, { dispatcher: dispatcher, @@ -955,7 +1120,9 @@ ) ), - React.createElement(FramedExample, {dashed: true, height: 394, + React.createElement(FramedExample, {dashed: true, + height: 394, + onContentsRendered: desktopRemoteFaceMuteRoomStore.activeRoomStore.forcedUpdate, summary: "Desktop room conversation remote face-mute", width: 298}, React.createElement("div", {className: "fx-embedded"}, @@ -964,6 +1131,7 @@ localPosterUrl: "sample-img/video-screen-local.png", mozLoop: navigator.mozLoop, onCallTerminated: function(){}, + remotePosterUrl: "sample-img/video-screen-remote.png", roomStore: desktopRemoteFaceMuteRoomStore}) ) ) @@ -1081,8 +1249,7 @@ isFirefox: true, localPosterUrl: "sample-img/video-screen-local.png", remotePosterUrl: "sample-img/video-screen-remote.png", - roomState: ROOM_STATES.HAS_PARTICIPANTS, - screenSharePosterUrl: "sample-img/video-screen-baz.png"}) + roomState: ROOM_STATES.HAS_PARTICIPANTS}) ) ), @@ -1102,8 +1269,7 @@ isFirefox: true, localPosterUrl: "sample-img/video-screen-local.png", remotePosterUrl: "sample-img/video-screen-remote.png", - roomState: ROOM_STATES.HAS_PARTICIPANTS, - screenSharePosterUrl: "sample-img/video-screen-baz.png"}) + roomState: ROOM_STATES.HAS_PARTICIPANTS}) ) ), @@ -1171,12 +1337,12 @@ cssClass: "standalone", dashed: true, height: 480, - onContentsRendered: updatingActiveRoomStore.forcedUpdate, + onContentsRendered: updatingMobileActiveRoomStore.forcedUpdate, summary: "Standalone room conversation (has-participants, 600x480)", width: 600}, React.createElement("div", {className: "standalone"}, React.createElement(StandaloneRoomView, { - activeRoomStore: updatingActiveRoomStore, + activeRoomStore: updatingMobileActiveRoomStore, dispatcher: dispatcher, isFirefox: true, localPosterUrl: "sample-img/video-screen-local.png", @@ -1189,12 +1355,12 @@ cssClass: "standalone", dashed: true, height: 480, - onContentsRendered: updatingSharingRoomStore.forcedUpdate, + onContentsRendered: updatingSharingRoomMobileStore.forcedUpdate, summary: "Standalone room convo (has-participants, receivingScreenShare, 600x480)", width: 600}, React.createElement("div", {className: "standalone", cssClass: "standalone"}, React.createElement(StandaloneRoomView, { - activeRoomStore: updatingSharingRoomStore, + activeRoomStore: updatingSharingRoomMobileStore, dispatcher: dispatcher, isFirefox: true, localPosterUrl: "sample-img/video-screen-local.png", @@ -1282,7 +1448,7 @@ // This simulates the mocha layout for errors which means we can run // this alongside our other unit tests but use the same harness. - var expectedWarningsCount = 23; + var expectedWarningsCount = 18; var warningsMismatch = caughtWarnings.length !== expectedWarningsCount; if (uncaughtError || warningsMismatch) { $("#results").append("
" + diff --git a/browser/components/loop/ui/ui-showcase.jsx b/browser/components/loop/ui/ui-showcase.jsx index 52d5089a216..92bd8367e5a 100644 --- a/browser/components/loop/ui/ui-showcase.jsx +++ b/browser/components/loop/ui/ui-showcase.jsx @@ -75,13 +75,25 @@ var dispatcher = new loop.Dispatcher(); - var mockSDK = _.extend({ + var MockSDK = function() { + dispatcher.register(this, [ + "setupStreamElements" + ]); + }; + + MockSDK.prototype = { + setupStreamElements: function() { + // Dummy function to stop warnings. + }, + sendTextChatMessage: function(message) { dispatcher.dispatch(new loop.shared.actions.ReceivedTextChatMessage({ message: message.message })); } - }, Backbone.Events); + }; + + var mockSDK = new MockSDK(); /** * Every view that uses an activeRoomStore needs its own; if they shared @@ -116,7 +128,6 @@ }); store.forcedUpdate = function forcedUpdate(contentWindow) { - // Since this is called by setTimeout, we don't want to lose any // exceptions if there's a problem and we need to debug, so... try { @@ -136,6 +147,17 @@ camera: {height: 480, orientation: 0, width: 640} }, remoteVideoEnabled: options.remoteVideoEnabled, + // Override the matchMedia, this is so that the correct version is + // used for the frame. + // + // Currently, we use an icky hack, and the showcase conspires with + // react-frame-component to set iframe.contentWindow.matchMedia onto + // the store. Once React context matures a bit (somewhere between + // 0.14 and 1.0, apparently): + // + // https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based + // + // we should be able to use those to clean this up. matchMedia: contentWindow.matchMedia.bind(contentWindow), roomState: options.roomState, videoMuted: !!options.videoMuted @@ -185,6 +207,10 @@ roomState: ROOM_STATES.HAS_PARTICIPANTS }); + var updatingMobileActiveRoomStore = makeActiveRoomStore({ + roomState: ROOM_STATES.HAS_PARTICIPANTS + }); + var localFaceMuteRoomStore = makeActiveRoomStore({ roomState: ROOM_STATES.HAS_PARTICIPANTS, videoMuted: true @@ -201,12 +227,19 @@ receivingScreenShare: true }); + var updatingSharingRoomMobileStore = makeActiveRoomStore({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + receivingScreenShare: true + }); + var loadingRemoteLoadingScreenStore = makeActiveRoomStore({ mediaConnected: false, + receivingScreenShare: true, roomState: ROOM_STATES.HAS_PARTICIPANTS, remoteSrcVideoObject: false }); var loadingScreenSharingRoomStore = makeActiveRoomStore({ + receivingScreenShare: true, roomState: ROOM_STATES.HAS_PARTICIPANTS }); @@ -234,7 +267,10 @@ }); var invitationRoomStore = new loop.store.RoomStore(dispatcher, { - mozLoop: navigator.mozLoop + mozLoop: navigator.mozLoop, + activeRoomStore: makeActiveRoomStore({ + roomState: ROOM_STATES.INIT + }) }); var roomStore = new loop.store.RoomStore(dispatcher, { @@ -253,6 +289,20 @@ }) }); + var desktopRoomStoreMedium = new loop.store.RoomStore(dispatcher, { + mozLoop: navigator.mozLoop, + activeRoomStore: makeActiveRoomStore({ + roomState: ROOM_STATES.HAS_PARTICIPANTS + }) + }); + + var desktopRoomStoreLarge = new loop.store.RoomStore(dispatcher, { + mozLoop: navigator.mozLoop, + activeRoomStore: makeActiveRoomStore({ + roomState: ROOM_STATES.HAS_PARTICIPANTS + }) + }); + var desktopLocalFaceMuteActiveRoomStore = makeActiveRoomStore({ roomState: ROOM_STATES.HAS_PARTICIPANTS, videoMuted: true @@ -272,15 +322,59 @@ activeRoomStore: desktopRemoteFaceMuteActiveRoomStore }); - var conversationStore = new loop.store.ConversationStore(dispatcher, { - client: {}, - mozLoop: navigator.mozLoop, - sdkDriver: mockSDK - }); var textChatStore = new loop.store.TextChatStore(dispatcher, { sdkDriver: mockSDK }); + /** + * Every view that uses an conversationStore needs its own; if they shared + * a conversation store, they'd interfere with each other. + * + * @param options + * @returns {loop.store.ConversationStore} + */ + function makeConversationStore() { + var roomDispatcher = new loop.Dispatcher(); + + var store = new loop.store.ConversationStore(dispatcher, { + client: {}, + mozLoop: navigator.mozLoop, + sdkDriver: mockSDK + }); + + store.forcedUpdate = function forcedUpdate(contentWindow) { + // Since this is called by setTimeout, we don't want to lose any + // exceptions if there's a problem and we need to debug, so... + try { + var newStoreState = { + // Override the matchMedia, this is so that the correct version is + // used for the frame. + // + // Currently, we use an icky hack, and the showcase conspires with + // react-frame-component to set iframe.contentWindow.matchMedia onto + // the store. Once React context matures a bit (somewhere between + // 0.14 and 1.0, apparently): + // + // https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based + // + // we should be able to use those to clean this up. + matchMedia: contentWindow.matchMedia.bind(contentWindow) + }; + + store.setStoreState(newStoreState); + } catch (ex) { + console.error("exception in forcedUpdate:", ex); + } + }; + + return store; + } + + var conversationStores = []; + for (var index = 0; index < 5; index++) { + conversationStores[index] = makeConversationStore(); + } + // Update the text chat store with the room info. textChatStore.updateRoomInfo(new sharedActions.UpdateRoomInfo({ roomName: "A Very Long Conversation Name", @@ -341,7 +435,7 @@ loop.store.StoreMixin.register({ activeRoomStore: activeRoomStore, - conversationStore: conversationStore, + conversationStore: conversationStores[0], textChatStore: textChatStore }); @@ -360,14 +454,6 @@ requestCallUrlInfo: noop }; - var mockConversationModel = new loop.shared.models.ConversationModel({ - callerId: "Mrs Jones", - urlCreationDate: (new Date() / 1000).toString() - }, { - sdk: mockSDK - }); - mockConversationModel.startSession = noop; - var mockWebSocket = new loop.CallConnectionWebSocket({ url: "fake", callId: "fakeId", @@ -763,7 +849,7 @@
+ store={conversationStores[0]} />
+ store={conversationStores[1]} />
+ store={conversationStores[0]} />
- +
- -
- -
+ +
+ +
- +
+ +
+
+ +
-
@@ -894,7 +1015,8 @@
@@ -911,6 +1033,7 @@ {/* Hide scrollbars here. Rotating loading div overflows and causes @@ -927,8 +1050,12 @@
- +
- + +
+ +
+
+ + +
+ +
+
+ +
-
@@ -964,6 +1131,7 @@ localPosterUrl="sample-img/video-screen-local.png" mozLoop={navigator.mozLoop} onCallTerminated={function(){}} + remotePosterUrl="sample-img/video-screen-remote.png" roomStore={desktopRemoteFaceMuteRoomStore} />
@@ -1081,8 +1249,7 @@ isFirefox={true} localPosterUrl="sample-img/video-screen-local.png" remotePosterUrl="sample-img/video-screen-remote.png" - roomState={ROOM_STATES.HAS_PARTICIPANTS} - screenSharePosterUrl="sample-img/video-screen-baz.png" /> + roomState={ROOM_STATES.HAS_PARTICIPANTS} />
@@ -1102,8 +1269,7 @@ isFirefox={true} localPosterUrl="sample-img/video-screen-local.png" remotePosterUrl="sample-img/video-screen-remote.png" - roomState={ROOM_STATES.HAS_PARTICIPANTS} - screenSharePosterUrl="sample-img/video-screen-baz.png" /> + roomState={ROOM_STATES.HAS_PARTICIPANTS} />
@@ -1171,12 +1337,12 @@ cssClass="standalone" dashed={true} height={480} - onContentsRendered={updatingActiveRoomStore.forcedUpdate} + onContentsRendered={updatingMobileActiveRoomStore.forcedUpdate} summary="Standalone room conversation (has-participants, 600x480)" width={600}>
" + diff --git a/browser/devtools/styleinspector/computed-view.js b/browser/devtools/styleinspector/computed-view.js index 3e0b61e9c38..f7e23dc843f 100644 --- a/browser/devtools/styleinspector/computed-view.js +++ b/browser/devtools/styleinspector/computed-view.js @@ -4,7 +4,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* globals overlays, StyleInspectorMenu */ +/* globals overlays, StyleInspectorMenu, loader, clipboardHelper, + _Iterator, StopIteration */ "use strict"; @@ -49,8 +50,7 @@ const HTML_NS = "http://www.w3.org/1999/xhtml"; * * @constructor */ -function UpdateProcess(aWin, aGenerator, aOptions) -{ +function UpdateProcess(aWin, aGenerator, aOptions) { this.win = aWin; this.iter = _Iterator(aGenerator); this.onItem = aOptions.onItem || function() {}; @@ -66,8 +66,7 @@ UpdateProcess.prototype = { /** * Schedule a new batch on the main loop. */ - schedule: function UP_schedule() - { + schedule: function() { if (this.canceled) { return; } @@ -78,8 +77,7 @@ UpdateProcess.prototype = { * Cancel the running process. onItem will not be called again, * and onCancel will be called. */ - cancel: function UP_cancel() - { + cancel: function() { if (this._timeout) { this.win.clearTimeout(this._timeout); this._timeout = 0; @@ -88,7 +86,7 @@ UpdateProcess.prototype = { this.onCancel(); }, - _timeoutHandler: function UP_timeoutHandler() { + _timeoutHandler: function() { this._timeout = null; try { this._runBatch(); @@ -104,10 +102,9 @@ UpdateProcess.prototype = { } }, - _runBatch: function Y_runBatch() - { + _runBatch: function() { let time = Date.now(); - while(!this.canceled) { + while (!this.canceled) { // Continue until iter.next() throws... let next = this.iter.next(); this.onItem(next[1]); @@ -120,9 +117,9 @@ UpdateProcess.prototype = { }; /** - * CssComputedView is a panel that manages the display of a table sorted by style. - * There should be one instance of CssComputedView per style display (of which there - * will generally only be one). + * CssComputedView is a panel that manages the display of a table + * sorted by style. There should be one instance of CssComputedView + * per style display (of which there will generally only be one). * * @param {Inspector} inspector toolbox panel * @param {Document} document The document that will contain the computed view. @@ -142,8 +139,8 @@ function CssComputedView(inspector, document, pageStyle) { this._outputParser = new OutputParser(); - let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]. - getService(Ci.nsIXULChromeRegistry); + let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"] + .getService(Ci.nsIXULChromeRegistry); this.getRTLAttr = chromeReg.isLocaleRTL("global") ? "rtl" : "ltr"; // Create bound methods. @@ -211,8 +208,7 @@ function CssComputedView(inspector, document, pageStyle) { * @param {string} aName The key to lookup. * @returns A localized version of the given key. */ -CssComputedView.l10n = function CssComputedView_l10n(aName) -{ +CssComputedView.l10n = function(aName) { try { return CssComputedView._strings.GetStringFromName(aName); } catch (ex) { @@ -251,8 +247,7 @@ CssComputedView.prototype = { this.pageStyle = pageStyle; }, - get includeBrowserStyles() - { + get includeBrowserStyles() { return this.includeBrowserStylesCheckbox.checked; }, @@ -264,8 +259,9 @@ CssComputedView.prototype = { }, /** - * Update the view with a new selected element. - * The CssComputedView panel will show the style information for the given element. + * Update the view with a new selected element. The CssComputedView panel + * will show the style information for the given element. + * * @param {NodeFront} aElement The highlighted node to get styles for. * @returns a promise that will be resolved when highlighting is complete. */ @@ -383,8 +379,7 @@ CssComputedView.prototype = { return {type, value}; }, - _createPropertyViews: function() - { + _createPropertyViews: function() { if (this._createViewsPromise) { return this._createViewsPromise; } @@ -396,7 +391,8 @@ CssComputedView.prototype = { this.numVisibleProperties = 0; let fragment = this.styleDocument.createDocumentFragment(); - this._createViewsProcess = new UpdateProcess(this.styleWindow, CssComputedView.propertyNames, { + this._createViewsProcess = new UpdateProcess( + this.styleWindow, CssComputedView.propertyNames, { onItem: (aPropertyName) => { // Per-item callback. let propView = new PropertyView(this, aPropertyName); @@ -426,8 +422,7 @@ CssComputedView.prototype = { /** * Refresh the panel content. */ - refreshPanel: function CssComputedView_refreshPanel() - { + refreshPanel: function() { if (!this.viewedElement) { return promise.resolve(); } @@ -443,12 +438,12 @@ CssComputedView.prototype = { onlyMatched: !this.includeBrowserStyles, markMatched: true }) - ]).then(([createViews, computed]) => { + ]).then(([, computed]) => { if (viewedElement !== this.viewedElement) { - return; + return promise.resolve(); } - this._matchedProperties = new Set; + this._matchedProperties = new Set(); for (let name in computed) { if (computed[name].matched) { this._matchedProperties.add(name); @@ -469,7 +464,8 @@ CssComputedView.prototype = { this._darkStripe = true; let deferred = promise.defer(); - this._refreshProcess = new UpdateProcess(this.styleWindow, this.propertyViews, { + this._refreshProcess = new UpdateProcess( + this.styleWindow, this.propertyViews, { onItem: (aPropView) => { aPropView.refresh(); }, @@ -511,8 +507,7 @@ CssComputedView.prototype = { * * @param {Event} aEvent the DOM Event object. */ - _onFilterStyles: function(aEvent) - { + _onFilterStyles: function(aEvent) { let win = this.styleWindow; if (this._filterChangedTimeout) { @@ -580,8 +575,7 @@ CssComputedView.prototype = { * * @param {Event} aEvent the DOM Event object. */ - _onIncludeBrowserStyles: function(aEvent) - { + _onIncludeBrowserStyles: function(aEvent) { this.refreshSourceFilter(); this.refreshPanel(); }, @@ -592,16 +586,14 @@ CssComputedView.prototype = { * document or one of thedocument's stylesheets. If .checked is false we * display all properties including those that come from UA stylesheets. */ - refreshSourceFilter: function CssComputedView_setSourceFilter() - { + refreshSourceFilter: function() { this._matchedProperties = null; this._sourceFilter = this.includeBrowserStyles ? CssLogic.FILTER.UA : CssLogic.FILTER.USER; }, - _onSourcePrefChanged: function CssComputedView__onSourcePrefChanged() - { + _onSourcePrefChanged: function() { for (let propView of this.propertyViews) { propView.updateSourceLinks(); } @@ -611,8 +603,7 @@ CssComputedView.prototype = { /** * The CSS as displayed by the UI. */ - createStyleViews: function CssComputedView_createStyleViews() - { + createStyleViews: function() { if (CssComputedView.propertyNames) { return; } @@ -641,8 +632,8 @@ CssComputedView.prototype = { this._createPropertyViews().then(null, e => { if (!this._isDestroyed) { - console.warn("The creation of property views was cancelled because the " + - "computed-view was destroyed before it was done creating views"); + console.warn("The creation of property views was cancelled because " + + "the computed-view was destroyed before it was done creating views"); } else { console.error(e); } @@ -654,18 +645,16 @@ CssComputedView.prototype = { * * @return {Set} If a property name is in the set, it has matching selectors. */ - get matchedProperties() - { - return this._matchedProperties || new Set; + get matchedProperties() { + return this._matchedProperties || new Set(); }, /** * Focus the window on mousedown. * - * @param aEvent The event object + * @param event The event object */ - focusWindow: function(aEvent) - { + focusWindow: function(event) { let win = this.styleDocument.defaultView; win.focus(); }, @@ -707,8 +696,8 @@ CssComputedView.prototype = { let win = this.styleDocument.defaultView; let text = win.getSelection().toString().trim(); - // Tidy up block headings by moving CSS property names and their values onto - // the same line and inserting a colon between them. + // Tidy up block headings by moving CSS property names and their + // values onto the same line and inserting a colon between them. let textArray = text.split(/[\r\n]+/); let result = ""; @@ -737,8 +726,7 @@ CssComputedView.prototype = { /** * Destructor for CssComputedView. */ - destroy: function CssComputedView_destroy() - { + destroy: function() { this.viewedElement = null; this._outputParser = null; @@ -819,8 +807,7 @@ PropertyInfo.prototype = { * @param {string} aName the CSS property name for which this PropertyView * instance will render the rules. */ -function PropertyView(aTree, aName) -{ +function PropertyView(aTree, aName) { this.tree = aTree; this.name = aName; this.getRTLAttr = aTree.getRTLAttr; @@ -864,32 +851,28 @@ PropertyView.prototype = { * @return {string} the computed style for the current property of the * currently highlighted element. */ - get value() - { + get value() { return this.propertyInfo.value; }, /** * An easy way to access the CssPropertyInfo behind this PropertyView. */ - get propertyInfo() - { + get propertyInfo() { return this._propertyInfo; }, /** * Does the property have any matched selectors? */ - get hasMatchedSelectors() - { + get hasMatchedSelectors() { return this.tree.matchedProperties.has(this.name); }, /** * Should this property be visible? */ - get visible() - { + get visible() { if (!this.tree.viewedElement) { return false; } @@ -913,8 +896,7 @@ PropertyView.prototype = { * Returns the className that should be assigned to the propertyView. * @return string */ - get propertyHeaderClassName() - { + get propertyHeaderClassName() { if (this.visible) { let isDark = this.tree._darkStripe = !this.tree._darkStripe; return isDark ? "property-view row-striped" : "property-view"; @@ -927,8 +909,7 @@ PropertyView.prototype = { * container. * @return string */ - get propertyContentClassName() - { + get propertyContentClassName() { if (this.visible) { let isDark = this.tree._darkStripe; return isDark ? "property-content row-striped" : "property-content"; @@ -940,8 +921,7 @@ PropertyView.prototype = { * Build the markup for on computed style * @return Element */ - buildMain: function PropertyView_buildMain() - { + buildMain: function() { let doc = this.tree.styleDocument; // Build the container element @@ -998,8 +978,7 @@ PropertyView.prototype = { return this.element; }, - buildSelectorContainer: function PropertyView_buildSelectorContainer() - { + buildSelectorContainer: function() { let doc = this.tree.styleDocument; let element = doc.createElementNS(HTML_NS, "div"); element.setAttribute("class", this.propertyContentClassName); @@ -1013,8 +992,7 @@ PropertyView.prototype = { /** * Refresh the panel's CSS property value. */ - refresh: function PropertyView_refresh() - { + refresh: function() { this.element.className = this.propertyHeaderClassName; this.element.nextElementSibling.className = this.propertyContentClassName; @@ -1051,8 +1029,7 @@ PropertyView.prototype = { /** * Refresh the panel matched rules. */ - refreshMatchedSelectors: function PropertyView_refreshMatchedSelectors() - { + refreshMatchedSelectors: function() { let hasMatchedSelectors = this.hasMatchedSelectors; this.matchedSelectorsContainer.parentNode.hidden = !hasMatchedSelectors; @@ -1063,28 +1040,29 @@ PropertyView.prototype = { } if (this.matchedExpanded && hasMatchedSelectors) { - return this.tree.pageStyle.getMatchedSelectors(this.tree.viewedElement, this.name).then(matched => { - if (!this.matchedExpanded) { - return; - } + return this.tree.pageStyle + .getMatchedSelectors(this.tree.viewedElement, this.name) + .then(matched => { + if (!this.matchedExpanded) { + return promise.resolve(undefined); + } - this._matchedSelectorResponse = matched; + this._matchedSelectorResponse = matched; - return this._buildMatchedSelectors().then(() => { - this.matchedExpander.setAttribute("open", ""); - this.tree.inspector.emit("computed-view-property-expanded"); - }); - }).then(null, console.error); - } else { - this.matchedSelectorsContainer.innerHTML = ""; - this.matchedExpander.removeAttribute("open"); - this.tree.inspector.emit("computed-view-property-collapsed"); - return promise.resolve(undefined); + return this._buildMatchedSelectors().then(() => { + this.matchedExpander.setAttribute("open", ""); + this.tree.inspector.emit("computed-view-property-expanded"); + }); + }).then(null, console.error); } + + this.matchedSelectorsContainer.innerHTML = ""; + this.matchedExpander.removeAttribute("open"); + this.tree.inspector.emit("computed-view-property-collapsed"); + return promise.resolve(undefined); }, - get matchedSelectors() - { + get matchedSelectors() { return this._matchedSelectorResponse; }, @@ -1130,13 +1108,13 @@ PropertyView.prototype = { * Provide access to the matched SelectorViews that we are currently * displaying. */ - get matchedSelectorViews() - { + get matchedSelectorViews() { if (!this._matchedSelectorViews) { this._matchedSelectorViews = []; this._matchedSelectorResponse.forEach( - function matchedSelectorViews_convert(aSelectorInfo) { - this._matchedSelectorViews.push(new SelectorView(this.tree, aSelectorInfo)); + function(aSelectorInfo) { + let selectorView = new SelectorView(this.tree, aSelectorInfo); + this._matchedSelectorViews.push(selectorView); }, this); } return this._matchedSelectorViews; @@ -1146,8 +1124,7 @@ PropertyView.prototype = { * Update all the selector source links to reflect whether we're linking to * original sources (e.g. Sass files). */ - updateSourceLinks: function PropertyView_updateSourceLinks() - { + updateSourceLinks: function() { if (!this._matchedSelectorViews) { return; } @@ -1162,8 +1139,7 @@ PropertyView.prototype = { * @param {Event} aEvent Used to determine the class name of the targets click * event. */ - onMatchedToggle: function PropertyView_onMatchedToggle(aEvent) - { + onMatchedToggle: function(aEvent) { if (aEvent.shiftKey) { return; } @@ -1175,8 +1151,7 @@ PropertyView.prototype = { /** * The action when a user clicks on the MDN help link for a property. */ - mdnLinkClick: function PropertyView_mdnLinkClick(aEvent) - { + mdnLinkClick: function(aEvent) { let inspector = this.tree.inspector; if (inspector.target.tab) { @@ -1189,7 +1164,7 @@ PropertyView.prototype = { /** * Destroy this property view, removing event listeners */ - destroy: function PropertyView_destroy() { + destroy: function() { this.element.removeEventListener("dblclick", this.onMatchedToggle, false); this.element.removeEventListener("keydown", this.onKeyDown, false); this.element = null; @@ -1210,8 +1185,7 @@ PropertyView.prototype = { * @param CssComputedView aTree, the owning CssComputedView * @param aSelectorInfo */ -function SelectorView(aTree, aSelectorInfo) -{ +function SelectorView(aTree, aSelectorInfo) { this.tree = aTree; this.selectorInfo = aSelectorInfo; this._cacheStatusNames(); @@ -1245,8 +1219,7 @@ SelectorView.prototype = { * * @return {void} */ - _cacheStatusNames: function SelectorView_cacheStatusNames() - { + _cacheStatusNames: function() { if (SelectorView.STATUS_NAMES.length) { return; } @@ -1256,7 +1229,7 @@ SelectorView.prototype = { if (i > CssLogic.STATUS.UNMATCHED) { let value = CssComputedView.l10n("rule.status." + status); // Replace normal spaces with non-breaking spaces - SelectorView.STATUS_NAMES[i] = value.replace(/ /g, '\u00A0'); + SelectorView.STATUS_NAMES[i] = value.replace(/ /g, "\u00A0"); } } }, @@ -1264,21 +1237,18 @@ SelectorView.prototype = { /** * A localized version of cssRule.status */ - get statusText() - { + get statusText() { return SelectorView.STATUS_NAMES[this.selectorInfo.status]; }, /** * Get class name for selector depending on status */ - get statusClass() - { + get statusClass() { return SelectorView.CLASS_NAMES[this.selectorInfo.status - 1]; }, - get href() - { + get href() { if (this._href) { return this._href; } @@ -1287,19 +1257,15 @@ SelectorView.prototype = { return this._href; }, - get sourceText() - { + get sourceText() { return this.selectorInfo.sourceText; }, - - get value() - { + get value() { return this.selectorInfo.value; }, - get outputFragment() - { + get outputFragment() { // Sadly, because this fragment is added to the template by DOM Templater // we lose any events that are attached. This means that URLs will open in a // new window. At some point we should fix this by stopping using the @@ -1320,8 +1286,7 @@ SelectorView.prototype = { * Update the text of the source link to reflect whether we're showing * original sources or not. */ - updateSourceLink: function() - { + updateSourceLink: function() { return this.updateSource().then((oldSource) => { if (oldSource != this.source && this.tree.element) { let selector = '[sourcelocation="' + oldSource + '"]'; @@ -1337,8 +1302,7 @@ SelectorView.prototype = { /** * Update the 'source' store based on our original sources preference. */ - updateSource: function() - { + updateSource: function() { let rule = this.selectorInfo.rule; this.sheet = rule.parentStyleSheet; @@ -1373,8 +1337,7 @@ SelectorView.prototype = { /** * Open the style editor if the RETURN key was pressed. */ - maybeOpenStyleEditor: function(aEvent) - { + maybeOpenStyleEditor: function(aEvent) { let keyEvent = Ci.nsIDOMKeyEvent; if (aEvent.keyCode == keyEvent.DOM_VK_RETURN) { this.openStyleEditor(); @@ -1391,8 +1354,7 @@ SelectorView.prototype = { * * @param aEvent The click event */ - openStyleEditor: function(aEvent) - { + openStyleEditor: function(aEvent) { let inspector = this.tree.inspector; let rule = this.selectorInfo.rule; @@ -1401,15 +1363,8 @@ SelectorView.prototype = { // // If the stylesheet is a content stylesheet we send it to the style // editor else we display it in the view source window. - let sheet = rule.parentStyleSheet; - if (!sheet || sheet.isSystem) { - let contentDoc = null; - if (this.tree.viewedElement.isLocal_toBeDeprecated()) { - let rawNode = this.tree.viewedElement.rawNode(); - if (rawNode) { - contentDoc = rawNode.ownerDocument; - } - } + let parentStyleSheet = rule.parentStyleSheet; + if (!parentStyleSheet || parentStyleSheet.isSystem) { let toolbox = gDevTools.getToolbox(inspector.target); toolbox.viewSource(rule.href, rule.line); return; @@ -1447,7 +1402,7 @@ function createChild(aParent, aTag, aAttributes={}) { if (aAttributes.hasOwnProperty(attr)) { if (attr === "textContent") { elt.textContent = aAttributes[attr]; - } else if(attr === "child") { + } else if (attr === "child") { elt.appendChild(aAttributes[attr]); } else { elt.setAttribute(attr, aAttributes[attr]); diff --git a/browser/devtools/styleinspector/rule-view.js b/browser/devtools/styleinspector/rule-view.js index ac6853cf671..34dbe7bc80f 100644 --- a/browser/devtools/styleinspector/rule-view.js +++ b/browser/devtools/styleinspector/rule-view.js @@ -5,7 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* globals overlays, Services, EventEmitter, StyleInspectorMenu, - clipboardHelper, _strings, domUtils, AutocompletePopup */ + clipboardHelper, _strings, domUtils, AutocompletePopup, loader, + osString */ "use strict"; @@ -209,7 +210,7 @@ ElementStyle.prototype = { filter: this.showUserAgentStyles ? "ua" : undefined, }).then(entries => { if (this.destroyed) { - return; + return promise.resolve(undefined); } // Make sure the dummy element has been created before continuing... @@ -236,14 +237,12 @@ ElementStyle.prototype = { // We're done with the previous list of rules. delete this._refreshRules; - - return null; }); }).then(null, e => { // populate is often called after a setTimeout, // the connection may already be closed. if (this.destroyed) { - return; + return promise.resolve(undefined); } return promiseWarn(e); }); @@ -636,7 +635,7 @@ Rule.prototype = { disabled.delete(this.style); } - let promise = aModifications.apply().then(() => { + let modificationsPromise = aModifications.apply().then(() => { let cssProps = {}; for (let cssProp of parseDeclarations(this.style.cssText)) { cssProps[cssProp.name] = cssProp; @@ -668,8 +667,8 @@ Rule.prototype = { this.elementStyle._changed(); }).then(null, promiseWarn); - this._applyingModifications = promise; - return promise; + this._applyingModifications = modificationsPromise; + return modificationsPromise; }, /** @@ -1111,7 +1110,8 @@ TextProperty.prototype = { */ stringifyProperty: function() { // Get the displayed property value - let declaration = this.name + ": " + this.editor.committed.value + ";"; + let declaration = this.name + ": " + this.editor.valueSpan.textContent + + ";"; // Comment out property declarations that are not enabled if (!this.enabled) { @@ -1741,7 +1741,7 @@ CssRuleView.prototype = { refreshPanel: function() { // Ignore refreshes during editing or when no element is selected. if (this.isEditing || !this._elementStyle) { - return; + return promise.resolve(undefined); } // Repopulate the element style once the current modifications are done. @@ -1893,9 +1893,10 @@ CssRuleView.prototype = { /** * Creates an expandable container in the rule view - * @param {String} aLabel The label for the container header - * @param {Boolean} isPseudo Whether or not the container will hold - * pseudo element rules + * @param {String} aLabel + * The label for the container header + * @param {Boolean} isPseudo + * Whether or not the container will hold pseudo element rules * @return {DOMNode} The container element */ createExpandableContainer: function(aLabel, isPseudo = false) { @@ -1915,44 +1916,59 @@ CssRuleView.prototype = { container.classList.add("ruleview-expandable-container"); this.element.appendChild(container); - let toggleContainerVisibility = (isPseudo, showPseudo) => { - let isOpen = twisty.getAttribute("open"); - - if (isPseudo) { - this._showPseudoElements = !!showPseudo; - - Services.prefs.setBoolPref("devtools.inspector.show_pseudo_elements", - this.showPseudoElements); - - header.classList.toggle("show-expandable-container", - this.showPseudoElements); - - isOpen = !this.showPseudoElements; - } else { - header.classList.toggle("show-expandable-container"); - } - - if (isOpen) { - twisty.removeAttribute("open"); - } else { - twisty.setAttribute("open", "true"); - } - }; - header.addEventListener("dblclick", () => { - toggleContainerVisibility(isPseudo, !this.showPseudoElements); + this._toggleContainerVisibility(twisty, header, isPseudo, + !this.showPseudoElements); }, false); + twisty.addEventListener("click", () => { - toggleContainerVisibility(isPseudo, !this.showPseudoElements); + this._toggleContainerVisibility(twisty, header, isPseudo, + !this.showPseudoElements); }, false); if (isPseudo) { - toggleContainerVisibility(isPseudo, this.showPseudoElements); + this._toggleContainerVisibility(twisty, header, isPseudo, + this.showPseudoElements); } return container; }, + /** + * Toggle the visibility of an expandable container + * @param {DOMNode} twisty + * clickable toggle DOM Node + * @param {DOMNode} header + * expandable container header DOM Node + * @param {Boolean} isPseudo + * whether or not the container will hold pseudo element rules + * @param {Boolean} showPseudo + * whether or not pseudo element rules should be displayed + */ + _toggleContainerVisibility: function(twisty, header, isPseudo, showPseudo) { + let isOpen = twisty.getAttribute("open"); + + if (isPseudo) { + this._showPseudoElements = !!showPseudo; + + Services.prefs.setBoolPref("devtools.inspector.show_pseudo_elements", + this.showPseudoElements); + + header.classList.toggle("show-expandable-container", + this.showPseudoElements); + + isOpen = !this.showPseudoElements; + } else { + header.classList.toggle("show-expandable-container"); + } + + if (isOpen) { + twisty.removeAttribute("open"); + } else { + twisty.setAttribute("open", "true"); + } + }, + _getRuleViewHeaderClassName: function(isPseudo) { let baseClassName = "theme-gutter ruleview-header"; return isPseudo ? baseClassName + " ruleview-expandable-header" : diff --git a/browser/devtools/styleinspector/style-inspector-menu.js b/browser/devtools/styleinspector/style-inspector-menu.js index d4826fddbbf..422ad352099 100644 --- a/browser/devtools/styleinspector/style-inspector-menu.js +++ b/browser/devtools/styleinspector/style-inspector-menu.js @@ -231,6 +231,7 @@ StyleInspectorMenu.prototype = { this.menuitemCopy.hidden = !this._hasTextSelected(); this.menuitemCopyColor.hidden = !this._isColorPopup(); this.menuitemCopyImageDataUrl.hidden = !this._isImageUrl(); + this.menuitemCopyUrl.hidden = !this._isImageUrl(); this.menuitemCopyRule.hidden = true; this.menuitemCopyLocation.hidden = true; @@ -378,6 +379,10 @@ StyleInspectorMenu.prototype = { * Retrieve the url for the selected image and copy it to the clipboard */ _onCopyUrl: function() { + if (!this._clickedNodeInfo) { + return; + } + clipboardHelper.copyString(this._clickedNodeInfo.value.url); }, diff --git a/browser/devtools/styleinspector/test/browser_ruleview_copy_styles.js b/browser/devtools/styleinspector/test/browser_ruleview_copy_styles.js index ba1455dd84a..8e2c35d5bec 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_copy_styles.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_copy_styles.js @@ -52,6 +52,20 @@ add_task(function*() { copyRule: false } }, + { + desc: "Test Copy Property Value with Priority", + node: ruleEditor.rule.textProps[3].editor.valueSpan, + menuItem: contextmenu.menuitemCopyPropertyValue, + expectedPattern: "#00F !important", + hidden: { + copyLocation: true, + copyPropertyDeclaration: false, + copyPropertyName: true, + copyPropertyValue: false, + copySelector: true, + copyRule: false + } + }, { desc: "Test Copy Property Declaration", node: ruleEditor.rule.textProps[2].editor.nameSpan, @@ -66,6 +80,20 @@ add_task(function*() { copyRule: false } }, + { + desc: "Test Copy Property Declaration with Priority", + node: ruleEditor.rule.textProps[3].editor.nameSpan, + menuItem: contextmenu.menuitemCopyPropertyDeclaration, + expectedPattern: "border-color: #00F !important;", + hidden: { + copyLocation: true, + copyPropertyDeclaration: false, + copyPropertyName: false, + copyPropertyValue: true, + copySelector: true, + copyRule: false + } + }, { desc: "Test Copy Rule", node: ruleEditor.rule.textProps[2].editor.nameSpan, @@ -74,6 +102,7 @@ add_task(function*() { "\tcolor: #F00;[\\r\\n]+" + "\tbackground-color: #00F;[\\r\\n]+" + "\tfont-size: 12px;[\\r\\n]+" + + "\tborder-color: #00F !important;[\\r\\n]+" + "}", hidden: { copyLocation: true, @@ -124,6 +153,7 @@ add_task(function*() { "\t\/\\* color: #F00; \\*\/[\\r\\n]+" + "\tbackground-color: #00F;[\\r\\n]+" + "\tfont-size: 12px;[\\r\\n]+" + + "\tborder-color: #00F !important;[\\r\\n]+" + "}", hidden: { copyLocation: true, diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_context-menu-copy-urls.js b/browser/devtools/styleinspector/test/browser_styleinspector_context-menu-copy-urls.js index a34722c339c..bbb7fc2f42a 100644 --- a/browser/devtools/styleinspector/test/browser_styleinspector_context-menu-copy-urls.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_context-menu-copy-urls.js @@ -80,6 +80,7 @@ function* testCopyUrlToClipboard({view, inspector}, type, selector, expected) { yield popup; info("Context menu is displayed"); + ok(!view._contextmenu.menuitemCopyUrl.hidden, "\"Copy URL\" menu entry is displayed"); ok(!view._contextmenu.menuitemCopyImageDataUrl.hidden, "\"Copy Image Data-URL\" menu entry is displayed"); if (type == "data-uri") { diff --git a/browser/devtools/styleinspector/test/doc_copystyles.css b/browser/devtools/styleinspector/test/doc_copystyles.css index b3221dc5407..7494c11a6fc 100644 --- a/browser/devtools/styleinspector/test/doc_copystyles.css +++ b/browser/devtools/styleinspector/test/doc_copystyles.css @@ -6,4 +6,5 @@ html, body, #testid { color: #F00; background-color: #00F; font-size: 12px; + border-color: #00F !important; } diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 48e5d17b748..ed83214006a 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -558,6 +558,7 @@ @RESPATH@/components/AlarmsManager.manifest @RESPATH@/components/Push.js @RESPATH@/components/Push.manifest +@RESPATH@/components/PushClient.js @RESPATH@/components/PushNotificationService.js @RESPATH@/components/SlowScriptDebug.manifest @@ -637,6 +638,7 @@ @RESPATH@/components/nsUrlClassifierHashCompleter.js @RESPATH@/components/nsUrlClassifierListManager.js @RESPATH@/components/nsUrlClassifierLib.js +@RESPATH@/components/PrivateBrowsingTrackingProtectionWhitelist.js @RESPATH@/components/url-classifier.xpt #endif diff --git a/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties b/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties index f61b20c17d8..f0ca0b10826 100644 --- a/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties +++ b/browser/locales/en-US/chrome/browser/customizableui/customizableWidgets.properties @@ -97,6 +97,9 @@ quit-button.tooltiptext.mac = Quit %1$S (%2$S) # approval before you change it. loop-call-button3.label = Hello loop-call-button3.tooltiptext = Start a conversation +# LOCALIZATION NOTE(loop-call-button3-pb.tooltiptext): Shown when the button is +# placed inside a Private Browsing window. %S is the value of loop-call-button3.label. +loop-call-button3-pb.tooltiptext = %S is not available in Private Browsing social-share-button.label = Share This Page social-share-button.tooltiptext = Share this page diff --git a/browser/locales/en-US/chrome/browser/loop/loop.properties b/browser/locales/en-US/chrome/browser/loop/loop.properties index 83503a312f8..436529e43e8 100644 --- a/browser/locales/en-US/chrome/browser/loop/loop.properties +++ b/browser/locales/en-US/chrome/browser/loop/loop.properties @@ -206,6 +206,8 @@ active_screenshare_button_title=Stop sharing inactive_screenshare_button_title=Share your screen share_tabs_button_title2=Share your Tabs share_windows_button_title=Share other Windows +self_view_hidden_message=Self-view hidden but still being sent; resize window to show + ## LOCALIZATION NOTE (call_with_contact_title): The title displayed ## when calling a contact. Don't translate the part between {{..}} because diff --git a/browser/themes/windows/browser-aero.css b/browser/themes/windows/browser-aero.css index 899414dc606..700a91f8714 100644 --- a/browser/themes/windows/browser-aero.css +++ b/browser/themes/windows/browser-aero.css @@ -115,7 +115,7 @@ .titlebar-button { border: none; margin: 0 !important; - padding: 12px 17px; + padding: 10px 17px; } #main-window[sizemode=maximized] .titlebar-button { @@ -147,6 +147,20 @@ list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-white); } + #titlebar-min:-moz-lwtheme { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-themes); + } + #titlebar-max:-moz-lwtheme { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-themes); + } + #main-window[sizemode="maximized"] #titlebar-max:-moz-lwtheme { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-themes); + } + #titlebar-close:-moz-lwtheme { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-themes); + } + + /* the 12px image renders a 10px icon, and the 10px upscaled gets rounded to 12.5, which * rounds up to 13px, which makes the icon one pixel too big on 1.25dppx. Fix: */ @media (min-resolution: 1.20dppx) and (max-resolution: 1.45dppx) { @@ -222,20 +236,32 @@ background-color: Highlight; } + #titlebar-min { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-highcontrast); + } #titlebar-min:hover { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-highlight); + list-style-image: url(chrome://browser/skin/caption-buttons.svg#minimize-highcontrast-hover); } + #titlebar-max { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-highcontrast); + } #titlebar-max:hover { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-highlight); + list-style-image: url(chrome://browser/skin/caption-buttons.svg#maximize-highcontrast-hover); } + #main-window[sizemode="maximized"] #titlebar-max { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-highcontrast); + } #main-window[sizemode="maximized"] #titlebar-max:hover { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-highlight); + list-style-image: url(chrome://browser/skin/caption-buttons.svg#restore-highcontrast-hover); } + #titlebar-close { + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-highcontrast); + } #titlebar-close:hover { - list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-highlight); + list-style-image: url(chrome://browser/skin/caption-buttons.svg#close-highcontrast-hover); } } } diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css index a251d08a75b..a805935a4ab 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -659,7 +659,7 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { -moz-padding-end: 5px; } -#nav-bar .toolbarbutton-1[type=panel]:not(#back-button):not(#forward-button):not(#feed-button):not(#PanelUI-menu-button), +#nav-bar .toolbarbutton-1[type=panel], #nav-bar .toolbarbutton-1[type=menu]:not(#back-button):not(#forward-button):not(#feed-button):not(#PanelUI-menu-button) { padding-left: 5px; padding-right: 5px; @@ -771,8 +771,8 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba width: 32px; } -#nav-bar .toolbarbutton-1[type=panel]:not(#back-button):not(#forward-button):not(#feed-button):not(#PanelUI-menu-button) > .toolbarbutton-icon, -#nav-bar .toolbarbutton-1[type=panel]:not(#back-button):not(#forward-button):not(#feed-button):not(#PanelUI-menu-button) > .toolbarbutton-badge-container, +#nav-bar .toolbarbutton-1[type=panel] > .toolbarbutton-icon, +#nav-bar .toolbarbutton-1[type=panel] > .toolbarbutton-badge-container, #nav-bar .toolbarbutton-1[type=menu]:not(#back-button):not(#forward-button):not(#feed-button):not(#PanelUI-menu-button) > .toolbarbutton-icon, #nav-bar .toolbarbutton-1[type=menu]:not(#back-button):not(#forward-button):not(#feed-button):not(#PanelUI-menu-button) > .toolbarbutton-badge-container, #nav-bar .toolbarbutton-1[type=menu] > .toolbarbutton-text /* hack for add-ons that forcefully display the label */ { @@ -1203,6 +1203,11 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba -moz-padding-end: 2px; } +/* overlap the urlbar's border */ +#PopupAutoCompleteRichResult { + margin-top: -1px; +} + @media (-moz-os-version: windows-xp), (-moz-os-version: windows-vista), (-moz-os-version: windows-win7) { @@ -1246,6 +1251,11 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba .searchbar-textbox:not(:-moz-lwtheme)[focused] { box-shadow: 0 0 0 1px Highlight inset; } + + /* overlap the urlbar's border and inset box-shadow */ + #PopupAutoCompleteRichResult:not(:-moz-lwtheme) { + margin-top: -2px; + } } @media not all and (-moz-os-version: windows-xp) { diff --git a/browser/themes/windows/caption-buttons.svg b/browser/themes/windows/caption-buttons.svg index 4b7c75a013a..a50d953b92c 100644 --- a/browser/themes/windows/caption-buttons.svg +++ b/browser/themes/windows/caption-buttons.svg @@ -9,7 +9,7 @@ fill: none; } - g:not(#close) { + g:not([id|="close"]) { shape-rendering: crispEdges; } @@ -21,17 +21,36 @@ display: initial; } - [id$="-highlight"] > g { + g.highlight { + stroke-width: 1.9px; + } + + g.themes { + stroke: #fff; + stroke-width: 1.9px; + } + + .outer-stroke { + stroke: #000; + stroke-width: 3.6; + opacity: .75; + } + + .restore-background-window { + stroke-width: .9; + } + + [id$="-highcontrast-hover"] > g { stroke: HighlightText; } [id$="-white"] > g { stroke: #fff; } + - - + @@ -43,13 +62,46 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp index b600fecb27a..d3887496ab6 100644 --- a/build/clang-plugin/clang-plugin.cpp +++ b/build/clang-plugin/clang-plugin.cpp @@ -1,6 +1,7 @@ /* 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 http://mozilla.org/MPL/2.0/. */ + #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" @@ -56,7 +57,6 @@ private: ScopeChecker(Scope scope_) : scope(scope_) {} virtual void run(const MatchFinder::MatchResult &Result); - void noteInferred(QualType T, DiagnosticsEngine &Diag); private: Scope scope; }; @@ -64,7 +64,6 @@ private: class NonHeapClassChecker : public MatchFinder::MatchCallback { public: virtual void run(const MatchFinder::MatchResult &Result); - void noteInferred(QualType T, DiagnosticsEngine &Diag); }; class ArithmeticArgChecker : public MatchFinder::MatchCallback { @@ -97,6 +96,16 @@ private: virtual void run(const MatchFinder::MatchResult &Result); }; + class NeedsNoVTableTypeChecker : public MatchFinder::MatchCallback { + public: + virtual void run(const MatchFinder::MatchResult &Result); + }; + + class NonMemMovableChecker : public MatchFinder::MatchCallback { + public: + virtual void run(const MatchFinder::MatchResult &Result); + }; + ScopeChecker stackClassChecker; ScopeChecker globalClassChecker; NonHeapClassChecker nonheapClassChecker; @@ -106,6 +115,8 @@ private: NoAddRefReleaseOnReturnChecker noAddRefReleaseOnReturnChecker; RefCountedInsideLambdaChecker refCountedInsideLambdaChecker; ExplicitOperatorBoolChecker explicitOperatorBoolChecker; + NeedsNoVTableTypeChecker needsNoVTableTypeChecker; + NonMemMovableChecker nonMemMovableChecker; MatchFinder astMatcher; }; @@ -217,6 +228,51 @@ bool isInterestingDeclForImplicitConversion(const Decl *decl) { } +class CustomTypeAnnotation { + enum ReasonKind { + RK_None, + RK_Direct, + RK_ArrayElement, + RK_BaseClass, + RK_Field, + }; + struct AnnotationReason { + QualType Type; + ReasonKind Kind; + const FieldDecl *Field; + + bool valid() const { return Kind != RK_None; } + }; + typedef DenseMap ReasonCache; + + const char *Spelling; + const char *Pretty; + ReasonCache Cache; + +public: + CustomTypeAnnotation(const char *Spelling, const char *Pretty) + : Spelling(Spelling), Pretty(Pretty) {}; + + // Checks if this custom annotation "effectively affects" the given type. + bool hasEffectiveAnnotation(QualType T) { + return directAnnotationReason(T).valid(); + } + void dumpAnnotationReason(DiagnosticsEngine &Diag, QualType T, SourceLocation Loc); + +private: + bool hasLiteralAnnotation(QualType T) const; + AnnotationReason directAnnotationReason(QualType T); +}; + +static CustomTypeAnnotation StackClass = + CustomTypeAnnotation("moz_stack_class", "stack"); +static CustomTypeAnnotation GlobalClass = + CustomTypeAnnotation("moz_global_class", "global"); +static CustomTypeAnnotation NonHeapClass = + CustomTypeAnnotation("moz_nonheap_class", "non-heap"); +static CustomTypeAnnotation MustUse = + CustomTypeAnnotation("moz_must_use", "must-use"); + class MozChecker : public ASTConsumer, public RecursiveASTVisitor { DiagnosticsEngine &Diag; const CompilerInstance &CI; @@ -232,29 +288,29 @@ public: TraverseDecl(ctx.getTranslationUnitDecl()); } - static bool hasCustomAnnotation(const Decl *d, const char *spelling) { - AnnotateAttr *attr = d->getAttr(); - if (!attr) - return false; + static bool hasCustomAnnotation(const Decl *D, const char *Spelling) { + iterator_range > Attrs = + D->specific_attrs(); - return attr->getAnnotation() == spelling; + for (AnnotateAttr *Attr : Attrs) { + if (Attr->getAnnotation() == Spelling) { + return true; + } + } + + return false; } void HandleUnusedExprResult(const Stmt *stmt) { const Expr* E = dyn_cast_or_null(stmt); if (E) { - // XXX It would be nice if we could use getAsTagDecl, - // but our version of clang is too old. - // (getAsTagDecl would also cover enums etc.) QualType T = E->getType(); - CXXRecordDecl *decl = T->getAsCXXRecordDecl(); - if (decl) { - decl = decl->getDefinition(); - if (decl && hasCustomAnnotation(decl, "moz_must_use")) { - unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID( - DiagnosticIDs::Error, "Unused MOZ_MUST_USE value of type %0"); - Diag.Report(E->getLocStart(), errorID) << T; - } + if (MustUse.hasEffectiveAnnotation(T)) { + unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Error, "Unused value of must-use type %0"); + + Diag.Report(E->getLocStart(), errorID) << T; + MustUse.dumpAnnotationReason(Diag, T, E->getLocStart()); } } } @@ -378,102 +434,6 @@ public: } }; -/** - * Where classes may be allocated. Regular classes can be allocated anywhere, - * non-heap classes on the stack or as static variables, and stack classes only - * on the stack. Note that stack classes subsumes non-heap classes. - */ -enum ClassAllocationNature { - RegularClass = 0, - NonHeapClass = 1, - StackClass = 2, - GlobalClass = 3 -}; - -/// A cached data of whether classes are stack classes, non-heap classes, or -/// neither. -DenseMap > inferredAllocCauses; - -ClassAllocationNature getClassAttrs(QualType T); - -ClassAllocationNature getClassAttrs(CXXRecordDecl *D) { - // Normalize so that D points to the definition if it exists. If it doesn't, - // then we can't allocate it anyways. - if (!D->hasDefinition()) - return RegularClass; - D = D->getDefinition(); - // Base class: anyone with this annotation is obviously a stack class - if (MozChecker::hasCustomAnnotation(D, "moz_stack_class")) - return StackClass; - // Base class: anyone with this annotation is obviously a global class - if (MozChecker::hasCustomAnnotation(D, "moz_global_class")) - return GlobalClass; - - // See if we cached the result. - DenseMap >::iterator it = - inferredAllocCauses.find(D); - if (it != inferredAllocCauses.end()) { - return it->second.second; - } - - // Continue looking, we might be a stack class yet. Even if we're a nonheap - // class, it might be possible that we've inferred to be a stack class. - ClassAllocationNature type = RegularClass; - if (MozChecker::hasCustomAnnotation(D, "moz_nonheap_class")) { - type = NonHeapClass; - } - inferredAllocCauses.insert(std::make_pair(D, - std::make_pair((const Decl *)0, type))); - - // Look through all base cases to figure out if the parent is a stack class or - // a non-heap class. Since we might later infer to also be a stack class, keep - // going. - for (CXXRecordDecl::base_class_iterator base = D->bases_begin(), - e = D->bases_end(); base != e; ++base) { - ClassAllocationNature super = getClassAttrs(base->getType()); - if (super == StackClass) { - inferredAllocCauses[D] = std::make_pair( - base->getType()->getAsCXXRecordDecl(), StackClass); - return StackClass; - } else if (super == GlobalClass) { - inferredAllocCauses[D] = std::make_pair( - base->getType()->getAsCXXRecordDecl(), GlobalClass); - return GlobalClass; - } else if (super == NonHeapClass) { - inferredAllocCauses[D] = std::make_pair( - base->getType()->getAsCXXRecordDecl(), NonHeapClass); - type = NonHeapClass; - } - } - - // Maybe it has a member which is a stack class. - for (RecordDecl::field_iterator field = D->field_begin(), e = D->field_end(); - field != e; ++field) { - ClassAllocationNature fieldType = getClassAttrs(field->getType()); - if (fieldType == StackClass) { - inferredAllocCauses[D] = std::make_pair(*field, StackClass); - return StackClass; - } else if (fieldType == GlobalClass) { - inferredAllocCauses[D] = std::make_pair(*field, GlobalClass); - return GlobalClass; - } else if (fieldType == NonHeapClass) { - inferredAllocCauses[D] = std::make_pair(*field, NonHeapClass); - type = NonHeapClass; - } - } - - return type; -} - -ClassAllocationNature getClassAttrs(QualType T) { - while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe()) - T = arrTy->getElementType(); - CXXRecordDecl *clazz = T->getAsCXXRecordDecl(); - return clazz ? getClassAttrs(clazz) : RegularClass; -} - /// A cached data of whether classes are refcounted or not. typedef DenseMap > RefCountedMap; @@ -527,7 +487,88 @@ bool isClassRefCounted(QualType T) { while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe()) T = arrTy->getElementType(); CXXRecordDecl *clazz = T->getAsCXXRecordDecl(); - return clazz ? isClassRefCounted(clazz) : RegularClass; + return clazz ? isClassRefCounted(clazz) : false; +} + +/// A cached data of whether classes are memmovable, and if not, what declaration +/// makes them non-movable +typedef DenseMap InferredMovability; +InferredMovability inferredMovability; + +bool isClassNonMemMovable(QualType T); +const CXXRecordDecl* isClassNonMemMovableWorker(QualType T); + +const CXXRecordDecl* isClassNonMemMovableWorker(const CXXRecordDecl *D) { + // If we have a definition, then we want to standardize our reference to point + // to the definition node. If we don't have a definition, that means that either + // we only have a forward declaration of the type in our file, or we are being + // passed a template argument which is not used, and thus never instantiated by + // clang. + // As the argument isn't used, we can't memmove it (as we don't know it's size), + // which means not reporting an error is OK. + if (!D->hasDefinition()) { + return 0; + } + D = D->getDefinition(); + + // Are we explicitly marked as non-memmovable class? + if (MozChecker::hasCustomAnnotation(D, "moz_non_memmovable")) { + return D; + } + + // Look through all base cases to figure out if the parent is a non-memmovable class. + for (CXXRecordDecl::base_class_const_iterator base = D->bases_begin(); + base != D->bases_end(); ++base) { + const CXXRecordDecl *result = isClassNonMemMovableWorker(base->getType()); + if (result) { + return result; + } + } + + // Look through all members to figure out if a member is a non-memmovable class. + for (RecordDecl::field_iterator field = D->field_begin(), e = D->field_end(); + field != e; ++field) { + const CXXRecordDecl *result = isClassNonMemMovableWorker(field->getType()); + if (result) { + return result; + } + } + + return 0; +} + +const CXXRecordDecl* isClassNonMemMovableWorker(QualType T) { + while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe()) + T = arrTy->getElementType(); + const CXXRecordDecl *clazz = T->getAsCXXRecordDecl(); + return clazz ? isClassNonMemMovableWorker(clazz) : 0; +} + +bool isClassNonMemMovable(const CXXRecordDecl *D) { + InferredMovability::iterator it = + inferredMovability.find(D); + if (it != inferredMovability.end()) + return !!it->second; + const CXXRecordDecl *result = isClassNonMemMovableWorker(D); + inferredMovability.insert(std::make_pair(D, result)); + return !!result; +} + +bool isClassNonMemMovable(QualType T) { + while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe()) + T = arrTy->getElementType(); + const CXXRecordDecl *clazz = T->getAsCXXRecordDecl(); + return clazz ? isClassNonMemMovable(clazz) : false; +} + +const CXXRecordDecl* findWhyClassIsNonMemMovable(QualType T) { + while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe()) + T = arrTy->getElementType(); + CXXRecordDecl *clazz = T->getAsCXXRecordDecl(); + InferredMovability::iterator it = + inferredMovability.find(clazz); + assert(it != inferredMovability.end()); + return it->second; } template @@ -540,6 +581,13 @@ bool IsInSystemHeader(const ASTContext &AC, const T &D) { return SourceManager.isInSystemHeader(ExpansionLoc); } +bool typeHasVTable(QualType T) { + while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe()) + T = arrTy->getElementType(); + CXXRecordDecl* offender = T->getAsCXXRecordDecl(); + return offender && offender->hasDefinition() && offender->isDynamicClass(); +} + } namespace clang { @@ -548,19 +596,19 @@ namespace ast_matchers { /// This matcher will match any class with the stack class assertion or an /// array of such classes. AST_MATCHER(QualType, stackClassAggregate) { - return getClassAttrs(Node) == StackClass; + return StackClass.hasEffectiveAnnotation(Node); } /// This matcher will match any class with the global class assertion or an /// array of such classes. AST_MATCHER(QualType, globalClassAggregate) { - return getClassAttrs(Node) == GlobalClass; + return GlobalClass.hasEffectiveAnnotation(Node); } /// This matcher will match any class with the stack class assertion or an /// array of such classes. AST_MATCHER(QualType, nonheapClassAggregate) { - return getClassAttrs(Node) == NonHeapClass; + return NonHeapClass.hasEffectiveAnnotation(Node); } /// This matcher will match any function declaration that is declared as a heap @@ -694,11 +742,126 @@ AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, #endif +AST_MATCHER(QualType, hasVTable) { + return typeHasVTable(Node); +} + +AST_MATCHER(CXXRecordDecl, hasNeedsNoVTableTypeAttr) { + return MozChecker::hasCustomAnnotation(&Node, "moz_needs_no_vtable_type"); +} + +/// This matcher will select classes which are non-memmovable +AST_MATCHER(QualType, isNonMemMovable) { + return isClassNonMemMovable(Node); +} + +/// This matcher will select classes which require a memmovable template arg +AST_MATCHER(CXXRecordDecl, needsMemMovable) { + return MozChecker::hasCustomAnnotation(&Node, "moz_needs_memmovable_type"); +} + } } namespace { +void CustomTypeAnnotation::dumpAnnotationReason(DiagnosticsEngine &Diag, QualType T, SourceLocation Loc) { + unsigned InheritsID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Note, "%1 is a %0 type because it inherits from a %0 type %2"); + unsigned MemberID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Note, "%1 is a %0 type because member %2 is a %0 type %3"); + unsigned ArrayID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Note, "%1 is a %0 type because it is an array of %0 type %2"); + unsigned TemplID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Note, "%1 is a %0 type because it has a template argument %0 type %2"); + + AnnotationReason Reason = directAnnotationReason(T); + for (;;) { + switch (Reason.Kind) { + case RK_ArrayElement: + Diag.Report(Loc, ArrayID) + << Pretty << T << Reason.Type; + break; + case RK_BaseClass: + { + const CXXRecordDecl *Decl = T->getAsCXXRecordDecl(); + assert(Decl && "This type should be a C++ class"); + + Diag.Report(Decl->getLocation(), InheritsID) + << Pretty << T << Reason.Type; + break; + } + case RK_Field: + Diag.Report(Reason.Field->getLocation(), MemberID) + << Pretty << T << Reason.Field << Reason.Type; + break; + default: + return; + } + + T = Reason.Type; + Reason = directAnnotationReason(T); + } +} + +bool CustomTypeAnnotation::hasLiteralAnnotation(QualType T) const { + if (const TagDecl *D = T->getAsTagDecl()) { + return MozChecker::hasCustomAnnotation(D, Spelling); + } + return false; +} + +CustomTypeAnnotation::AnnotationReason CustomTypeAnnotation::directAnnotationReason(QualType T) { + if (hasLiteralAnnotation(T)) { + AnnotationReason Reason = { T, RK_Direct, nullptr }; + return Reason; + } + + // Check if we have a cached answer + void *Key = T.getAsOpaquePtr(); + ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr()); + if (Cached != Cache.end()) { + return Cached->second; + } + + // Check if we have a type which we can recurse into + if (const ArrayType *Array = T->getAsArrayTypeUnsafe()) { + if (hasEffectiveAnnotation(Array->getElementType())) { + AnnotationReason Reason = { Array->getElementType(), RK_ArrayElement, nullptr }; + Cache[Key] = Reason; + return Reason; + } + } + + // Recurse into base classes + if (const CXXRecordDecl *Decl = T->getAsCXXRecordDecl()) { + if (Decl->hasDefinition()) { + Decl = Decl->getDefinition(); + + for (const CXXBaseSpecifier &Base : Decl->bases()) { + if (hasEffectiveAnnotation(Base.getType())) { + AnnotationReason Reason = { Base.getType(), RK_BaseClass, nullptr }; + Cache[Key] = Reason; + return Reason; + } + } + + // Recurse into members + for (const FieldDecl *Field : Decl->fields()) { + if (hasEffectiveAnnotation(Field->getType())) { + AnnotationReason Reason = { Field->getType(), RK_Field, Field }; + Cache[Key] = Reason; + return Reason; + } + } + } + } + + AnnotationReason Reason = { QualType(), RK_None, nullptr }; + Cache[Key] = Reason; + return Reason; +} + bool isPlacementNew(const CXXNewExpr *expr) { // Regular new expressions aren't placement new if (expr->getNumPlacementArgs() == 0) @@ -816,6 +979,18 @@ DiagnosticsMatcher::DiagnosticsMatcher() astMatcher.addMatcher(methodDecl(anyOf(hasName("operator bool"), hasName("operator _Bool"))).bind("node"), &explicitOperatorBoolChecker); + + astMatcher.addMatcher(classTemplateSpecializationDecl( + allOf(hasAnyTemplateArgument(refersToType(hasVTable())), + hasNeedsNoVTableTypeAttr())).bind("node"), + &needsNoVTableTypeChecker); + + // Handle non-mem-movable template specializations + astMatcher.addMatcher(classTemplateSpecializationDecl( + allOf(needsMemMovable(), + hasAnyTemplateArgument(refersToType(isNonMemMovable()))) + ).bind("specialization"), + &nonMemMovableChecker); } void DiagnosticsMatcher::ScopeChecker::run( @@ -825,7 +1000,9 @@ void DiagnosticsMatcher::ScopeChecker::run( DiagnosticIDs::Error, "variable of type %0 only valid on the stack"); unsigned globalID = Diag.getDiagnosticIDs()->getCustomDiagID( DiagnosticIDs::Error, "variable of type %0 only valid as global"); - unsigned errorID = (scope == eGlobal) ? globalID : stackID; + + SourceLocation Loc; + QualType T; if (const VarDecl *d = Result.Nodes.getNodeAs("node")) { if (scope == eLocal) { // Ignore the match if it's a local variable. @@ -840,56 +1017,29 @@ void DiagnosticsMatcher::ScopeChecker::run( return; } - Diag.Report(d->getLocation(), errorID) << d->getType(); - noteInferred(d->getType(), Diag); + Loc = d->getLocation(); + T = d->getType(); } else if (const CXXNewExpr *expr = Result.Nodes.getNodeAs("node")) { // If it's placement new, then this match doesn't count. if (scope == eLocal && isPlacementNew(expr)) return; - Diag.Report(expr->getStartLoc(), errorID) << expr->getAllocatedType(); - noteInferred(expr->getAllocatedType(), Diag); + + Loc = expr->getStartLoc(); + T = expr->getAllocatedType(); } else if (const CallExpr *expr = Result.Nodes.getNodeAs("node")) { - QualType badType = GetCallReturnType(expr)->getPointeeType(); - Diag.Report(expr->getLocStart(), errorID) << badType; - noteInferred(badType, Diag); - } -} - -void DiagnosticsMatcher::ScopeChecker::noteInferred(QualType T, - DiagnosticsEngine &Diag) { - unsigned inheritsID = Diag.getDiagnosticIDs()->getCustomDiagID( - DiagnosticIDs::Note, - "%0 is a %2 class because it inherits from a %2 class %1"); - unsigned memberID = Diag.getDiagnosticIDs()->getCustomDiagID( - DiagnosticIDs::Note, - "%0 is a %3 class because member %1 is a %3 class %2"); - const char* attribute = (scope == eGlobal) ? - "moz_global_class" : "moz_stack_class"; - const char* type = (scope == eGlobal) ? - "global" : "stack"; - - // Find the CXXRecordDecl that is the local/global class of interest - while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe()) - T = arrTy->getElementType(); - CXXRecordDecl *clazz = T->getAsCXXRecordDecl(); - - // Direct result, we're done. - if (MozChecker::hasCustomAnnotation(clazz, attribute)) - return; - - const Decl *cause = inferredAllocCauses[clazz].first; - if (const CXXRecordDecl *CRD = dyn_cast(cause)) { - Diag.Report(clazz->getLocation(), inheritsID) << - T << CRD->getDeclName() << type; - } else if (const FieldDecl *FD = dyn_cast(cause)) { - Diag.Report(FD->getLocation(), memberID) << - T << FD << FD->getType() << type; + Loc = expr->getLocStart(); + T = GetCallReturnType(expr)->getPointeeType(); } - // Recursively follow this back. - noteInferred(cast(cause)->getType(), Diag); + if (scope == eLocal) { + Diag.Report(Loc, stackID) << T; + StackClass.dumpAnnotationReason(Diag, T, Loc); + } else if (scope == eGlobal) { + Diag.Report(Loc, globalID) << T; + GlobalClass.dumpAnnotationReason(Diag, T, Loc); + } } void DiagnosticsMatcher::NonHeapClassChecker::run( @@ -897,46 +1047,22 @@ void DiagnosticsMatcher::NonHeapClassChecker::run( DiagnosticsEngine &Diag = Result.Context->getDiagnostics(); unsigned stackID = Diag.getDiagnosticIDs()->getCustomDiagID( DiagnosticIDs::Error, "variable of type %0 is not valid on the heap"); + + SourceLocation Loc; + QualType T; if (const CXXNewExpr *expr = Result.Nodes.getNodeAs("node")) { // If it's placement new, then this match doesn't count. if (isPlacementNew(expr)) return; - Diag.Report(expr->getStartLoc(), stackID) << expr->getAllocatedType(); - noteInferred(expr->getAllocatedType(), Diag); + Loc = expr->getLocStart(); + T = expr->getAllocatedType(); } else if (const CallExpr *expr = Result.Nodes.getNodeAs("node")) { - QualType badType = GetCallReturnType(expr)->getPointeeType(); - Diag.Report(expr->getLocStart(), stackID) << badType; - noteInferred(badType, Diag); + Loc = expr->getLocStart(); + T = GetCallReturnType(expr)->getPointeeType(); } -} -void DiagnosticsMatcher::NonHeapClassChecker::noteInferred(QualType T, - DiagnosticsEngine &Diag) { - unsigned inheritsID = Diag.getDiagnosticIDs()->getCustomDiagID( - DiagnosticIDs::Note, - "%0 is a non-heap class because it inherits from a non-heap class %1"); - unsigned memberID = Diag.getDiagnosticIDs()->getCustomDiagID( - DiagnosticIDs::Note, - "%0 is a non-heap class because member %1 is a non-heap class %2"); - - // Find the CXXRecordDecl that is the stack class of interest - while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe()) - T = arrTy->getElementType(); - CXXRecordDecl *clazz = T->getAsCXXRecordDecl(); - - // Direct result, we're done. - if (MozChecker::hasCustomAnnotation(clazz, "moz_nonheap_class")) - return; - - const Decl *cause = inferredAllocCauses[clazz].first; - if (const CXXRecordDecl *CRD = dyn_cast(cause)) { - Diag.Report(clazz->getLocation(), inheritsID) << T << CRD->getDeclName(); - } else if (const FieldDecl *FD = dyn_cast(cause)) { - Diag.Report(FD->getLocation(), memberID) << T << FD << FD->getType(); - } - - // Recursively follow this back. - noteInferred(cast(cause)->getType(), Diag); + Diag.Report(Loc, stackID) << T; + NonHeapClass.dumpAnnotationReason(Diag, T, Loc); } void DiagnosticsMatcher::ArithmeticArgChecker::run( @@ -1047,6 +1173,72 @@ void DiagnosticsMatcher::ExplicitOperatorBoolChecker::run( } } +void DiagnosticsMatcher::NeedsNoVTableTypeChecker::run( + const MatchFinder::MatchResult &Result) { + DiagnosticsEngine &Diag = Result.Context->getDiagnostics(); + unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Error, "%0 cannot be instantiated because %1 has a VTable"); + unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Note, "bad instantiation of %0 requested here"); + + const ClassTemplateSpecializationDecl *specialization = + Result.Nodes.getNodeAs("node"); + + // Get the offending template argument + QualType offender; + const TemplateArgumentList &args = + specialization->getTemplateInstantiationArgs(); + for (unsigned i = 0; i < args.size(); ++i) { + offender = args[i].getAsType(); + if (typeHasVTable(offender)) { + break; + } + } + + Diag.Report(specialization->getLocStart(), errorID) << specialization << offender; + Diag.Report(specialization->getPointOfInstantiation(), noteID) << specialization; +} + +void DiagnosticsMatcher::NonMemMovableChecker::run( + const MatchFinder::MatchResult &Result) { + DiagnosticsEngine &Diag = Result.Context->getDiagnostics(); + unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Error, "Cannot instantiate %0 with non-memmovable template argument %1"); + unsigned note1ID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Note, "instantiation of %0 requested here"); + unsigned note2ID = Diag.getDiagnosticIDs()->getCustomDiagID( + DiagnosticIDs::Note, "%0 is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on %1"); + unsigned note3ID = Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Note, "%0"); + + // Get the specialization + const ClassTemplateSpecializationDecl *specialization = + Result.Nodes.getNodeAs("specialization"); + SourceLocation requestLoc = specialization->getPointOfInstantiation(); + const CXXRecordDecl *templ = + specialization->getSpecializedTemplate()->getTemplatedDecl(); + + // Report an error for every template argument which is non-memmovable + const TemplateArgumentList &args = + specialization->getTemplateInstantiationArgs(); + for (unsigned i = 0; i < args.size(); ++i) { + QualType argType = args[i].getAsType(); + if (isClassNonMemMovable(args[i].getAsType())) { + const CXXRecordDecl *reason = findWhyClassIsNonMemMovable(argType); + Diag.Report(specialization->getLocation(), errorID) + << specialization << argType; + // XXX It would be really nice if we could get the instantiation stack information + // from Sema such that we could print a full template instantiation stack, however, + // it seems as though that information is thrown out by the time we get here so we + // can only report one level of template specialization (which in many cases won't + // be useful) + Diag.Report(requestLoc, note1ID) + << specialization; + Diag.Report(reason->getLocation(), note2ID) + << argType << reason; + } + } +} + class MozCheckAction : public PluginASTAction { public: ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI, StringRef fileName) override { diff --git a/build/clang-plugin/tests/TestGlobalClass.cpp b/build/clang-plugin/tests/TestGlobalClass.cpp index 88da22e9cd5..62d4d07b87e 100644 --- a/build/clang-plugin/tests/TestGlobalClass.cpp +++ b/build/clang-plugin/tests/TestGlobalClass.cpp @@ -16,9 +16,9 @@ void gobble(void *) { } void misuseGlobalClass(int len) { Global notValid; // expected-error {{variable of type 'Global' only valid as global}} - Global alsoNotValid[2]; // expected-error {{variable of type 'Global [2]' only valid as global}} + Global alsoNotValid[2]; // expected-error {{variable of type 'Global [2]' only valid as global}} expected-note {{'Global [2]' is a global type because it is an array of global type 'Global'}} static Global valid; // expected-error {{variable of type 'Global' only valid as global}} - static Global alsoValid[2]; // expected-error {{variable of type 'Global [2]' only valid as global}} + static Global alsoValid[2]; // expected-error {{variable of type 'Global [2]' only valid as global}} expected-note {{'Global [2]' is a global type because it is an array of global type 'Global'}} gobble(&valid); gobble(¬Valid); @@ -35,7 +35,7 @@ void misuseGlobalClass(int len) { Global valid; struct RandomClass { - Global nonstaticMember; // expected-note {{'RandomClass' is a global class because member 'nonstaticMember' is a global class 'Global'}} + Global nonstaticMember; // expected-note {{'RandomClass' is a global type because member 'nonstaticMember' is a global type 'Global'}} static Global staticMember; }; struct MOZ_GLOBAL_CLASS RandomGlobalClass { @@ -43,7 +43,7 @@ struct MOZ_GLOBAL_CLASS RandomGlobalClass { static Global staticMember; }; -struct BadInherit : Global {}; // expected-note {{'BadInherit' is a global class because it inherits from a global class 'Global'}} +struct BadInherit : Global {}; // expected-note {{'BadInherit' is a global type because it inherits from a global type 'Global'}} struct MOZ_GLOBAL_CLASS GoodInherit : Global {}; void misuseGlobalClassEvenMore(int len) { diff --git a/build/clang-plugin/tests/TestMultipleAnnotations.cpp b/build/clang-plugin/tests/TestMultipleAnnotations.cpp new file mode 100644 index 00000000000..cade13f9a08 --- /dev/null +++ b/build/clang-plugin/tests/TestMultipleAnnotations.cpp @@ -0,0 +1,17 @@ +#define MOZ_MUST_USE __attribute__((annotate("moz_must_use"))) +#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class"))) + +class MOZ_MUST_USE MOZ_STACK_CLASS TestClass {}; + +TestClass foo; // expected-error {{variable of type 'TestClass' only valid on the stack}} + +TestClass f() +{ + TestClass bar; + return bar; +} + +void g() +{ + f(); // expected-error {{Unused value of must-use type 'TestClass'}} +} diff --git a/build/clang-plugin/tests/TestMustUse.cpp b/build/clang-plugin/tests/TestMustUse.cpp index edcdb1a508c..33d6a8bd7e8 100644 --- a/build/clang-plugin/tests/TestMustUse.cpp +++ b/build/clang-plugin/tests/TestMustUse.cpp @@ -20,42 +20,42 @@ void use(MayUse&&); void use(bool); void foo() { - producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMustUsePointer(); - producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMayUse(); producesMayUsePointer(); producesMayUseRef(); { - producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMustUsePointer(); - producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMayUse(); producesMayUsePointer(); producesMayUseRef(); } if (true) { - producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMustUsePointer(); - producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMayUse(); producesMayUsePointer(); producesMayUseRef(); } else { - producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMustUsePointer(); - producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMayUse(); producesMayUsePointer(); producesMayUseRef(); } - if(true) producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} - else producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + if(true) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} + else producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} if(true) producesMustUsePointer(); else producesMustUsePointer(); - if(true) producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} - else producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + if(true) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} + else producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} if(true) producesMayUse(); else producesMayUse(); if(true) producesMayUsePointer(); @@ -63,18 +63,18 @@ void foo() { if(true) producesMayUseRef(); else producesMayUseRef(); - while (true) producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + while (true) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} while (true) producesMustUsePointer(); - while (true) producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + while (true) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} while (true) producesMayUse(); while (true) producesMayUsePointer(); while (true) producesMayUseRef(); - do producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + do producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} while (true); do producesMustUsePointer(); while (true); - do producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + do producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} while (true); do producesMayUse(); while (true); @@ -83,48 +83,48 @@ void foo() { do producesMayUseRef(); while (true); - for (;;) producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + for (;;) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} for (;;) producesMustUsePointer(); - for (;;) producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + for (;;) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} for (;;) producesMayUse(); for (;;) producesMayUsePointer(); for (;;) producesMayUseRef(); - for (producesMustUse();;); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + for (producesMustUse();;); // expected-error {{Unused value of must-use type 'MustUse'}} for (producesMustUsePointer();;); - for (producesMustUseRef();;); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + for (producesMustUseRef();;); // expected-error {{Unused value of must-use type 'MustUse'}} for (producesMayUse();;); for (producesMayUsePointer();;); for (producesMayUseRef();;); - for (;;producesMustUse()); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + for (;;producesMustUse()); // expected-error {{Unused value of must-use type 'MustUse'}} for (;;producesMustUsePointer()); - for (;;producesMustUseRef()); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + for (;;producesMustUseRef()); // expected-error {{Unused value of must-use type 'MustUse'}} for (;;producesMayUse()); for (;;producesMayUsePointer()); for (;;producesMayUseRef()); - use((producesMustUse(), false)); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + use((producesMustUse(), false)); // expected-error {{Unused value of must-use type 'MustUse'}} use((producesMustUsePointer(), false)); - use((producesMustUseRef(), false)); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + use((producesMustUseRef(), false)); // expected-error {{Unused value of must-use type 'MustUse'}} use((producesMayUse(), false)); use((producesMayUsePointer(), false)); use((producesMayUseRef(), false)); switch (1) { case 1: - producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMustUsePointer(); - producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMayUse(); producesMayUsePointer(); producesMayUseRef(); case 2: - producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} case 3: producesMustUsePointer(); case 4: - producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} case 5: producesMayUse(); case 6: @@ -132,9 +132,9 @@ void foo() { case 7: producesMayUseRef(); default: - producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMustUsePointer(); - producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}} + producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}} producesMayUse(); producesMayUsePointer(); producesMayUseRef(); diff --git a/build/clang-plugin/tests/TestNeedsNoVTableType.cpp b/build/clang-plugin/tests/TestNeedsNoVTableType.cpp new file mode 100644 index 00000000000..531a1c82a16 --- /dev/null +++ b/build/clang-plugin/tests/TestNeedsNoVTableType.cpp @@ -0,0 +1,94 @@ +#define MOZ_NEEDS_NO_VTABLE_TYPE __attribute__((annotate("moz_needs_no_vtable_type"))) + +template +struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer { // expected-error {{'PickyConsumer' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer' cannot be instantiated because 'G' has a VTable}} + T *m; +}; + +template +struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer_A { // expected-error {{'PickyConsumer_A' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer_A' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer_A' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer_A' cannot be instantiated because 'G' has a VTable}} + T *m; +}; +template +struct PickyConsumerWrapper { + PickyConsumer_A m; // expected-note {{bad instantiation of 'PickyConsumer_A' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A' requested here}} +}; + +template +struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer_B { // expected-error {{'PickyConsumer_B' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer_B' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer_B' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer_B' cannot be instantiated because 'G' has a VTable}} + T *m; +}; +template +struct PickyConsumerSubclass : PickyConsumer_B {}; // expected-note {{bad instantiation of 'PickyConsumer_B' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B' requested here}} + +template +struct NonPickyConsumer { + T *m; +}; + +struct A {}; +struct B : virtual A {}; +struct C : A {}; +struct D { + void d(); +}; +struct E { + virtual void e(); +}; +struct F : E { + virtual void e() final; +}; +struct G { + virtual void e() = 0; +}; + +void f() { + { + PickyConsumer a1; + PickyConsumerWrapper a2; + PickyConsumerSubclass a3; + NonPickyConsumer a4; + } + + { + PickyConsumer a1; // expected-note {{bad instantiation of 'PickyConsumer' requested here}} + PickyConsumerWrapper a2; + PickyConsumerSubclass a3; + NonPickyConsumer a4; + } + + { + PickyConsumer a1; + PickyConsumerWrapper a2; + PickyConsumerSubclass a3; + NonPickyConsumer a4; + } + + { + PickyConsumer a1; + PickyConsumerWrapper a2; + PickyConsumerSubclass a3; + NonPickyConsumer a4; + } + + { + PickyConsumer a1; // expected-note {{bad instantiation of 'PickyConsumer' requested here}} + PickyConsumerWrapper a2; + PickyConsumerSubclass a3; + NonPickyConsumer a4; + } + + { + PickyConsumer a1; // expected-note {{bad instantiation of 'PickyConsumer' requested here}} + PickyConsumerWrapper a2; + PickyConsumerSubclass a3; + NonPickyConsumer a4; + } + + { + PickyConsumer a1; // expected-note {{bad instantiation of 'PickyConsumer' requested here}} + PickyConsumerWrapper a2; + PickyConsumerSubclass a3; + NonPickyConsumer a4; + } +} diff --git a/build/clang-plugin/tests/TestNonHeapClass.cpp b/build/clang-plugin/tests/TestNonHeapClass.cpp index cf258ad0009..25538e8b20c 100644 --- a/build/clang-plugin/tests/TestNonHeapClass.cpp +++ b/build/clang-plugin/tests/TestNonHeapClass.cpp @@ -36,7 +36,7 @@ void misuseNonHeapClass(int len) { NonHeap validStatic; struct RandomClass { - NonHeap nonstaticMember; // expected-note {{'RandomClass' is a non-heap class because member 'nonstaticMember' is a non-heap class 'NonHeap'}} + NonHeap nonstaticMember; // expected-note {{'RandomClass' is a non-heap type because member 'nonstaticMember' is a non-heap type 'NonHeap'}} static NonHeap staticMember; }; struct MOZ_NONHEAP_CLASS RandomNonHeapClass { @@ -44,7 +44,7 @@ struct MOZ_NONHEAP_CLASS RandomNonHeapClass { static NonHeap staticMember; }; -struct BadInherit : NonHeap {}; // expected-note {{'BadInherit' is a non-heap class because it inherits from a non-heap class 'NonHeap'}} +struct BadInherit : NonHeap {}; // expected-note {{'BadInherit' is a non-heap type because it inherits from a non-heap type 'NonHeap'}} struct MOZ_NONHEAP_CLASS GoodInherit : NonHeap {}; void useStuffWrongly() { @@ -52,11 +52,11 @@ void useStuffWrongly() { gobble(new RandomClass); // expected-error {{variable of type 'RandomClass' is not valid on the heap}} } -// Stack class overrides non-heap classes. +// Stack class overrides non-heap typees. struct MOZ_STACK_CLASS StackClass {}; struct MOZ_NONHEAP_CLASS InferredStackClass : GoodInherit { NonHeap nonstaticMember; - StackClass stackClass; // expected-note {{'InferredStackClass' is a stack class because member 'stackClass' is a stack class 'StackClass'}} + StackClass stackClass; // expected-note {{'InferredStackClass' is a stack type because member 'stackClass' is a stack type 'StackClass'}} }; InferredStackClass global; // expected-error {{variable of type 'InferredStackClass' only valid on the stack}} diff --git a/build/clang-plugin/tests/TestNonMemMovable.cpp b/build/clang-plugin/tests/TestNonMemMovable.cpp new file mode 100644 index 00000000000..7f36b2e634f --- /dev/null +++ b/build/clang-plugin/tests/TestNonMemMovable.cpp @@ -0,0 +1,812 @@ +#define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable"))) +#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type"))) + +/* + These are a bunch of structs with variable levels of memmovability. + They will be used as template parameters to the various NeedyTemplates +*/ +struct MOZ_NON_MEMMOVABLE NonMovable {}; // expected-note-re + {{'{{.*}}' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'NonMovable'}} +struct Movable {}; + +// Subclasses +struct S_NonMovable : NonMovable {}; +struct S_Movable : Movable {}; + +// Members +struct W_NonMovable { + NonMovable m; +}; +struct W_Movable { + Movable m; +}; + +// Wrapped Subclasses +struct WS_NonMovable { + S_NonMovable m; +}; +struct WS_Movable { + S_Movable m; +}; + +// Combinations of the above +struct SW_NonMovable : W_NonMovable {}; +struct SW_Movable : W_Movable {}; + +struct SWS_NonMovable : WS_NonMovable {}; +struct SWS_Movable : WS_Movable {}; + +// Basic templated wrapper +template +struct Template_Inline { + T m; +}; + +template +struct Template_Ref { + T* m; +}; + +template +struct Template_Unused {}; + +template +struct MOZ_NON_MEMMOVABLE Template_NonMovable {}; // expected-note-re + {{'{{.*}}' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'Template_NonMovable<{{.*}}>'}} + +/* + These tests take the following form: + DECLARATIONS => Declarations of the templates which are either marked with MOZ_NEEDS_MEMMOVABLE_TYPE + or which instantiate a MOZ_NEEDS_MEMMOVABLE_TYPE through some mechanism. + BAD N => Instantiations of the wrapper template with each of the non-memmovable types. + The prefix S_ means subclass, W_ means wrapped. Each of these rows should produce an error + on the NeedyTemplate in question, and a note at the instantiation location of that template. + Unfortunately, on every case more complicated than bad1, the instantiation location is + within another template. Thus, the notes are expected on the template in question which + actually instantiates the MOZ_NEEDS_MEMMOVABLE_TYPE template. + GOOD N => Instantiations of the wrapper template with each of the memmovable types. + This is meant as a sanity check to ensure that we don't reject valid instantiations of + templates. + + + Note 1: Each set uses it's own types to ensure that they don't re-use each-other's template specializations. + If they did, then some of the error messages would not be emitted (as error messages are emitted for template + specializations, rather than for variable declarations) + + Note 2: Every instance of NeedyTemplate contains a member of type T. This is to ensure that T is actually + instantiated (if T is a template) by clang. If T isn't instantiated, then we can't actually tell if it is + NON_MEMMOVABLE. (This is OK in practice, as you cannot memmove a type which you don't know the size of). + + Note 3: There are a set of tests for specializations of NeedyTemplate at the bottom. For each set of tests, + these tests contribute two expected errors to the templates. +*/ + +// +// 1 - Unwrapped MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate1 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate1<{{.*}}>' with non-memmovable template argument '{{.*}}'}} + +void bad1() { + NeedyTemplate1 a1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 a2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 a3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 a4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 a5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 a6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + + NeedyTemplate1 > b1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > b2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > b3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > b4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > b5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > b6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + + NeedyTemplate1 > c1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c7; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c8; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c9; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c10; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c11; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} + NeedyTemplate1 > c12; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}} +} + +void good1() { + NeedyTemplate1 a1; + NeedyTemplate1 a2; + NeedyTemplate1 a3; + NeedyTemplate1 a4; + NeedyTemplate1 a5; + NeedyTemplate1 a6; + + NeedyTemplate1 > b1; + NeedyTemplate1 > b2; + NeedyTemplate1 > b3; + NeedyTemplate1 > b4; + NeedyTemplate1 > b5; + NeedyTemplate1 > b6; + + NeedyTemplate1 > c1; + NeedyTemplate1 > c2; + NeedyTemplate1 > c3; + NeedyTemplate1 > c4; + NeedyTemplate1 > c5; + NeedyTemplate1 > c6; + NeedyTemplate1 > c7; + NeedyTemplate1 > c8; + NeedyTemplate1 > c9; + NeedyTemplate1 > c10; + NeedyTemplate1 > c11; + NeedyTemplate1 > c12; + + NeedyTemplate1 > d1; + NeedyTemplate1 > d2; + NeedyTemplate1 > d3; + NeedyTemplate1 > d4; + NeedyTemplate1 > d5; + NeedyTemplate1 > d6; + NeedyTemplate1 > d7; + NeedyTemplate1 > d8; + NeedyTemplate1 > d9; + NeedyTemplate1 > d10; + NeedyTemplate1 > d11; + NeedyTemplate1 > d12; +} + +// +// 2 - Subclassed MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate2 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate2<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template +struct S_NeedyTemplate2 : NeedyTemplate2 {}; // expected-note-re 26 {{instantiation of 'NeedyTemplate2<{{.*}}>' requested here}} + +void bad2() { + S_NeedyTemplate2 a1; + S_NeedyTemplate2 a2; + S_NeedyTemplate2 a3; + S_NeedyTemplate2 a4; + S_NeedyTemplate2 a5; + S_NeedyTemplate2 a6; + + S_NeedyTemplate2 > b1; + S_NeedyTemplate2 > b2; + S_NeedyTemplate2 > b3; + S_NeedyTemplate2 > b4; + S_NeedyTemplate2 > b5; + S_NeedyTemplate2 > b6; + + S_NeedyTemplate2 > c1; + S_NeedyTemplate2 > c2; + S_NeedyTemplate2 > c3; + S_NeedyTemplate2 > c4; + S_NeedyTemplate2 > c5; + S_NeedyTemplate2 > c6; + S_NeedyTemplate2 > c7; + S_NeedyTemplate2 > c8; + S_NeedyTemplate2 > c9; + S_NeedyTemplate2 > c10; + S_NeedyTemplate2 > c11; + S_NeedyTemplate2 > c12; +} + +void good2() { + S_NeedyTemplate2 a1; + S_NeedyTemplate2 a2; + S_NeedyTemplate2 a3; + S_NeedyTemplate2 a4; + S_NeedyTemplate2 a5; + S_NeedyTemplate2 a6; + + S_NeedyTemplate2 > b1; + S_NeedyTemplate2 > b2; + S_NeedyTemplate2 > b3; + S_NeedyTemplate2 > b4; + S_NeedyTemplate2 > b5; + S_NeedyTemplate2 > b6; + + S_NeedyTemplate2 > c1; + S_NeedyTemplate2 > c2; + S_NeedyTemplate2 > c3; + S_NeedyTemplate2 > c4; + S_NeedyTemplate2 > c5; + S_NeedyTemplate2 > c6; + S_NeedyTemplate2 > c7; + S_NeedyTemplate2 > c8; + S_NeedyTemplate2 > c9; + S_NeedyTemplate2 > c10; + S_NeedyTemplate2 > c11; + S_NeedyTemplate2 > c12; + + S_NeedyTemplate2 > d1; + S_NeedyTemplate2 > d2; + S_NeedyTemplate2 > d3; + S_NeedyTemplate2 > d4; + S_NeedyTemplate2 > d5; + S_NeedyTemplate2 > d6; + S_NeedyTemplate2 > d7; + S_NeedyTemplate2 > d8; + S_NeedyTemplate2 > d9; + S_NeedyTemplate2 > d10; + S_NeedyTemplate2 > d11; + S_NeedyTemplate2 > d12; +} + +// +// 3 - Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate3 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate3<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template +struct W_NeedyTemplate3 { + NeedyTemplate3 m; // expected-note-re 26 {{instantiation of 'NeedyTemplate3<{{.*}}>' requested here}} +}; +void bad3() { + W_NeedyTemplate3 a1; + W_NeedyTemplate3 a2; + W_NeedyTemplate3 a3; + W_NeedyTemplate3 a4; + W_NeedyTemplate3 a5; + W_NeedyTemplate3 a6; + + W_NeedyTemplate3 > b1; + W_NeedyTemplate3 > b2; + W_NeedyTemplate3 > b3; + W_NeedyTemplate3 > b4; + W_NeedyTemplate3 > b5; + W_NeedyTemplate3 > b6; + + W_NeedyTemplate3 > c1; + W_NeedyTemplate3 > c2; + W_NeedyTemplate3 > c3; + W_NeedyTemplate3 > c4; + W_NeedyTemplate3 > c5; + W_NeedyTemplate3 > c6; + W_NeedyTemplate3 > c7; + W_NeedyTemplate3 > c8; + W_NeedyTemplate3 > c9; + W_NeedyTemplate3 > c10; + W_NeedyTemplate3 > c11; + W_NeedyTemplate3 > c12; +} + +void good3() { + W_NeedyTemplate3 a1; + W_NeedyTemplate3 a2; + W_NeedyTemplate3 a3; + W_NeedyTemplate3 a4; + W_NeedyTemplate3 a5; + W_NeedyTemplate3 a6; + + W_NeedyTemplate3 > b1; + W_NeedyTemplate3 > b2; + W_NeedyTemplate3 > b3; + W_NeedyTemplate3 > b4; + W_NeedyTemplate3 > b5; + W_NeedyTemplate3 > b6; + + W_NeedyTemplate3 > c1; + W_NeedyTemplate3 > c2; + W_NeedyTemplate3 > c3; + W_NeedyTemplate3 > c4; + W_NeedyTemplate3 > c5; + W_NeedyTemplate3 > c6; + W_NeedyTemplate3 > c7; + W_NeedyTemplate3 > c8; + W_NeedyTemplate3 > c9; + W_NeedyTemplate3 > c10; + W_NeedyTemplate3 > c11; + W_NeedyTemplate3 > c12; + + W_NeedyTemplate3 > d1; + W_NeedyTemplate3 > d2; + W_NeedyTemplate3 > d3; + W_NeedyTemplate3 > d4; + W_NeedyTemplate3 > d5; + W_NeedyTemplate3 > d6; + W_NeedyTemplate3 > d7; + W_NeedyTemplate3 > d8; + W_NeedyTemplate3 > d9; + W_NeedyTemplate3 > d10; + W_NeedyTemplate3 > d11; + W_NeedyTemplate3 > d12; +} + +// +// 4 - Wrapped Subclassed MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate4 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate4<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template +struct S_NeedyTemplate4 : NeedyTemplate4 {}; // expected-note-re 26 {{instantiation of 'NeedyTemplate4<{{.*}}>' requested here}} +template +struct WS_NeedyTemplate4 { + S_NeedyTemplate4 m; +}; +void bad4() { + WS_NeedyTemplate4 a1; + WS_NeedyTemplate4 a2; + WS_NeedyTemplate4 a3; + WS_NeedyTemplate4 a4; + WS_NeedyTemplate4 a5; + WS_NeedyTemplate4 a6; + + WS_NeedyTemplate4 > b1; + WS_NeedyTemplate4 > b2; + WS_NeedyTemplate4 > b3; + WS_NeedyTemplate4 > b4; + WS_NeedyTemplate4 > b5; + WS_NeedyTemplate4 > b6; + + WS_NeedyTemplate4 > c1; + WS_NeedyTemplate4 > c2; + WS_NeedyTemplate4 > c3; + WS_NeedyTemplate4 > c4; + WS_NeedyTemplate4 > c5; + WS_NeedyTemplate4 > c6; + WS_NeedyTemplate4 > c7; + WS_NeedyTemplate4 > c8; + WS_NeedyTemplate4 > c9; + WS_NeedyTemplate4 > c10; + WS_NeedyTemplate4 > c11; + WS_NeedyTemplate4 > c12; +} + +void good4() { + WS_NeedyTemplate4 a1; + WS_NeedyTemplate4 a2; + WS_NeedyTemplate4 a3; + WS_NeedyTemplate4 a4; + WS_NeedyTemplate4 a5; + WS_NeedyTemplate4 a6; + + WS_NeedyTemplate4 > b1; + WS_NeedyTemplate4 > b2; + WS_NeedyTemplate4 > b3; + WS_NeedyTemplate4 > b4; + WS_NeedyTemplate4 > b5; + WS_NeedyTemplate4 > b6; + + WS_NeedyTemplate4 > c1; + WS_NeedyTemplate4 > c2; + WS_NeedyTemplate4 > c3; + WS_NeedyTemplate4 > c4; + WS_NeedyTemplate4 > c5; + WS_NeedyTemplate4 > c6; + WS_NeedyTemplate4 > c7; + WS_NeedyTemplate4 > c8; + WS_NeedyTemplate4 > c9; + WS_NeedyTemplate4 > c10; + WS_NeedyTemplate4 > c11; + WS_NeedyTemplate4 > c12; + + WS_NeedyTemplate4 > d1; + WS_NeedyTemplate4 > d2; + WS_NeedyTemplate4 > d3; + WS_NeedyTemplate4 > d4; + WS_NeedyTemplate4 > d5; + WS_NeedyTemplate4 > d6; + WS_NeedyTemplate4 > d7; + WS_NeedyTemplate4 > d8; + WS_NeedyTemplate4 > d9; + WS_NeedyTemplate4 > d10; + WS_NeedyTemplate4 > d11; + WS_NeedyTemplate4 > d12; +} + +// +// 5 - Subclassed Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE +// + +template +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate5 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate5<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template +struct W_NeedyTemplate5 { + NeedyTemplate5 m; // expected-note-re 26 {{instantiation of 'NeedyTemplate5<{{.*}}>' requested here}} +}; +template +struct SW_NeedyTemplate5 : W_NeedyTemplate5 {}; +void bad5() { + SW_NeedyTemplate5 a1; + SW_NeedyTemplate5 a2; + SW_NeedyTemplate5 a3; + SW_NeedyTemplate5 a4; + SW_NeedyTemplate5 a5; + SW_NeedyTemplate5 a6; + + SW_NeedyTemplate5 > b1; + SW_NeedyTemplate5 > b2; + SW_NeedyTemplate5 > b3; + SW_NeedyTemplate5 > b4; + SW_NeedyTemplate5 > b5; + SW_NeedyTemplate5 > b6; + + SW_NeedyTemplate5 > c1; + SW_NeedyTemplate5 > c2; + SW_NeedyTemplate5 > c3; + SW_NeedyTemplate5 > c4; + SW_NeedyTemplate5 > c5; + SW_NeedyTemplate5 > c6; + SW_NeedyTemplate5 > c7; + SW_NeedyTemplate5 > c8; + SW_NeedyTemplate5 > c9; + SW_NeedyTemplate5 > c10; + SW_NeedyTemplate5 > c11; + SW_NeedyTemplate5 > c12; +} + +void good5() { + SW_NeedyTemplate5 a1; + SW_NeedyTemplate5 a2; + SW_NeedyTemplate5 a3; + SW_NeedyTemplate5 a4; + SW_NeedyTemplate5 a5; + SW_NeedyTemplate5 a6; + + SW_NeedyTemplate5 > b1; + SW_NeedyTemplate5 > b2; + SW_NeedyTemplate5 > b3; + SW_NeedyTemplate5 > b4; + SW_NeedyTemplate5 > b5; + SW_NeedyTemplate5 > b6; + + SW_NeedyTemplate5 > c1; + SW_NeedyTemplate5 > c2; + SW_NeedyTemplate5 > c3; + SW_NeedyTemplate5 > c4; + SW_NeedyTemplate5 > c5; + SW_NeedyTemplate5 > c6; + SW_NeedyTemplate5 > c7; + SW_NeedyTemplate5 > c8; + SW_NeedyTemplate5 > c9; + SW_NeedyTemplate5 > c10; + SW_NeedyTemplate5 > c11; + SW_NeedyTemplate5 > c12; + + SW_NeedyTemplate5 > d1; + SW_NeedyTemplate5 > d2; + SW_NeedyTemplate5 > d3; + SW_NeedyTemplate5 > d4; + SW_NeedyTemplate5 > d5; + SW_NeedyTemplate5 > d6; + SW_NeedyTemplate5 > d7; + SW_NeedyTemplate5 > d8; + SW_NeedyTemplate5 > d9; + SW_NeedyTemplate5 > d10; + SW_NeedyTemplate5 > d11; + SW_NeedyTemplate5 > d12; +} + +// +// 6 - MOZ_NEEDS_MEMMOVABLE_TYPE instantiated with default template argument +// +// Note: This has an extra error, because it also includes a test with the default template argument. +// + +template +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate6 {T m;}; // expected-error-re 27 {{Cannot instantiate 'NeedyTemplate6<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template +struct W_NeedyTemplate6 { + NeedyTemplate6 m; // expected-note-re 27 {{instantiation of 'NeedyTemplate6<{{.*}}>' requested here}} +}; +template +struct SW_NeedyTemplate6 : W_NeedyTemplate6 {}; +// We create a different NonMovable type here, as NeedyTemplate6 will already be instantiated with NonMovable +struct MOZ_NON_MEMMOVABLE NonMovable2 {}; // expected-note {{'NonMovable2' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'NonMovable2'}} +template +struct Defaulted_SW_NeedyTemplate6 { + SW_NeedyTemplate6 m; +}; +void bad6() { + Defaulted_SW_NeedyTemplate6 a1; + Defaulted_SW_NeedyTemplate6 a2; + Defaulted_SW_NeedyTemplate6 a3; + Defaulted_SW_NeedyTemplate6 a4; + Defaulted_SW_NeedyTemplate6 a5; + Defaulted_SW_NeedyTemplate6 a6; + + Defaulted_SW_NeedyTemplate6 > b1; + Defaulted_SW_NeedyTemplate6 > b2; + Defaulted_SW_NeedyTemplate6 > b3; + Defaulted_SW_NeedyTemplate6 > b4; + Defaulted_SW_NeedyTemplate6 > b5; + Defaulted_SW_NeedyTemplate6 > b6; + + Defaulted_SW_NeedyTemplate6 > c1; + Defaulted_SW_NeedyTemplate6 > c2; + Defaulted_SW_NeedyTemplate6 > c3; + Defaulted_SW_NeedyTemplate6 > c4; + Defaulted_SW_NeedyTemplate6 > c5; + Defaulted_SW_NeedyTemplate6 > c6; + Defaulted_SW_NeedyTemplate6 > c7; + Defaulted_SW_NeedyTemplate6 > c8; + Defaulted_SW_NeedyTemplate6 > c9; + Defaulted_SW_NeedyTemplate6 > c10; + Defaulted_SW_NeedyTemplate6 > c11; + Defaulted_SW_NeedyTemplate6 > c12; + + Defaulted_SW_NeedyTemplate6<> c13; +} + +void good6() { + Defaulted_SW_NeedyTemplate6 a1; + Defaulted_SW_NeedyTemplate6 a2; + Defaulted_SW_NeedyTemplate6 a3; + Defaulted_SW_NeedyTemplate6 a4; + Defaulted_SW_NeedyTemplate6 a5; + Defaulted_SW_NeedyTemplate6 a6; + + Defaulted_SW_NeedyTemplate6 > b1; + Defaulted_SW_NeedyTemplate6 > b2; + Defaulted_SW_NeedyTemplate6 > b3; + Defaulted_SW_NeedyTemplate6 > b4; + Defaulted_SW_NeedyTemplate6 > b5; + Defaulted_SW_NeedyTemplate6 > b6; + + Defaulted_SW_NeedyTemplate6 > c1; + Defaulted_SW_NeedyTemplate6 > c2; + Defaulted_SW_NeedyTemplate6 > c3; + Defaulted_SW_NeedyTemplate6 > c4; + Defaulted_SW_NeedyTemplate6 > c5; + Defaulted_SW_NeedyTemplate6 > c6; + Defaulted_SW_NeedyTemplate6 > c7; + Defaulted_SW_NeedyTemplate6 > c8; + Defaulted_SW_NeedyTemplate6 > c9; + Defaulted_SW_NeedyTemplate6 > c10; + Defaulted_SW_NeedyTemplate6 > c11; + Defaulted_SW_NeedyTemplate6 > c12; + + Defaulted_SW_NeedyTemplate6 > d1; + Defaulted_SW_NeedyTemplate6 > d2; + Defaulted_SW_NeedyTemplate6 > d3; + Defaulted_SW_NeedyTemplate6 > d4; + Defaulted_SW_NeedyTemplate6 > d5; + Defaulted_SW_NeedyTemplate6 > d6; + Defaulted_SW_NeedyTemplate6 > d7; + Defaulted_SW_NeedyTemplate6 > d8; + Defaulted_SW_NeedyTemplate6 > d9; + Defaulted_SW_NeedyTemplate6 > d10; + Defaulted_SW_NeedyTemplate6 > d11; + Defaulted_SW_NeedyTemplate6 > d12; +} + +// +// 7 - MOZ_NEEDS_MEMMOVABLE_TYPE instantiated as default template argument +// + +template +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate7 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate7<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template > +struct Defaulted_Templated_NeedyTemplate7 {Q m;}; // expected-note-re 26 {{instantiation of 'NeedyTemplate7<{{.*}}>' requested here}} +void bad7() { + Defaulted_Templated_NeedyTemplate7 a1; + Defaulted_Templated_NeedyTemplate7 a2; + Defaulted_Templated_NeedyTemplate7 a3; + Defaulted_Templated_NeedyTemplate7 a4; + Defaulted_Templated_NeedyTemplate7 a5; + Defaulted_Templated_NeedyTemplate7 a6; + + Defaulted_Templated_NeedyTemplate7 > b1; + Defaulted_Templated_NeedyTemplate7 > b2; + Defaulted_Templated_NeedyTemplate7 > b3; + Defaulted_Templated_NeedyTemplate7 > b4; + Defaulted_Templated_NeedyTemplate7 > b5; + Defaulted_Templated_NeedyTemplate7 > b6; + + Defaulted_Templated_NeedyTemplate7 > c1; + Defaulted_Templated_NeedyTemplate7 > c2; + Defaulted_Templated_NeedyTemplate7 > c3; + Defaulted_Templated_NeedyTemplate7 > c4; + Defaulted_Templated_NeedyTemplate7 > c5; + Defaulted_Templated_NeedyTemplate7 > c6; + Defaulted_Templated_NeedyTemplate7 > c7; + Defaulted_Templated_NeedyTemplate7 > c8; + Defaulted_Templated_NeedyTemplate7 > c9; + Defaulted_Templated_NeedyTemplate7 > c10; + Defaulted_Templated_NeedyTemplate7 > c11; + Defaulted_Templated_NeedyTemplate7 > c12; +} + +void good7() { + Defaulted_Templated_NeedyTemplate7 a1; + Defaulted_Templated_NeedyTemplate7 a2; + Defaulted_Templated_NeedyTemplate7 a3; + Defaulted_Templated_NeedyTemplate7 a4; + Defaulted_Templated_NeedyTemplate7 a5; + Defaulted_Templated_NeedyTemplate7 a6; + + Defaulted_Templated_NeedyTemplate7 > b1; + Defaulted_Templated_NeedyTemplate7 > b2; + Defaulted_Templated_NeedyTemplate7 > b3; + Defaulted_Templated_NeedyTemplate7 > b4; + Defaulted_Templated_NeedyTemplate7 > b5; + Defaulted_Templated_NeedyTemplate7 > b6; + + Defaulted_Templated_NeedyTemplate7 > c1; + Defaulted_Templated_NeedyTemplate7 > c2; + Defaulted_Templated_NeedyTemplate7 > c3; + Defaulted_Templated_NeedyTemplate7 > c4; + Defaulted_Templated_NeedyTemplate7 > c5; + Defaulted_Templated_NeedyTemplate7 > c6; + Defaulted_Templated_NeedyTemplate7 > c7; + Defaulted_Templated_NeedyTemplate7 > c8; + Defaulted_Templated_NeedyTemplate7 > c9; + Defaulted_Templated_NeedyTemplate7 > c10; + Defaulted_Templated_NeedyTemplate7 > c11; + Defaulted_Templated_NeedyTemplate7 > c12; + + Defaulted_Templated_NeedyTemplate7 > d1; + Defaulted_Templated_NeedyTemplate7 > d2; + Defaulted_Templated_NeedyTemplate7 > d3; + Defaulted_Templated_NeedyTemplate7 > d4; + Defaulted_Templated_NeedyTemplate7 > d5; + Defaulted_Templated_NeedyTemplate7 > d6; + Defaulted_Templated_NeedyTemplate7 > d7; + Defaulted_Templated_NeedyTemplate7 > d8; + Defaulted_Templated_NeedyTemplate7 > d9; + Defaulted_Templated_NeedyTemplate7 > d10; + Defaulted_Templated_NeedyTemplate7 > d11; + Defaulted_Templated_NeedyTemplate7 > d12; +} + +// +// 8 - Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE instantiated as default template argument +// + +template +struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate8 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate8<{{.*}}>' with non-memmovable template argument '{{.*}}'}} +template > +struct Defaulted_Templated_NeedyTemplate8 {Q m;}; // expected-note-re 26 {{instantiation of 'NeedyTemplate8<{{.*}}>' requested here}} +template +struct W_Defaulted_Templated_NeedyTemplate8 { + Defaulted_Templated_NeedyTemplate8 m; +}; +void bad8() { + W_Defaulted_Templated_NeedyTemplate8 a1; + W_Defaulted_Templated_NeedyTemplate8 a2; + W_Defaulted_Templated_NeedyTemplate8 a3; + W_Defaulted_Templated_NeedyTemplate8 a4; + W_Defaulted_Templated_NeedyTemplate8 a5; + W_Defaulted_Templated_NeedyTemplate8 a6; + + W_Defaulted_Templated_NeedyTemplate8 > b1; + W_Defaulted_Templated_NeedyTemplate8 > b2; + W_Defaulted_Templated_NeedyTemplate8 > b3; + W_Defaulted_Templated_NeedyTemplate8 > b4; + W_Defaulted_Templated_NeedyTemplate8 > b5; + W_Defaulted_Templated_NeedyTemplate8 > b6; + + W_Defaulted_Templated_NeedyTemplate8 > c1; + W_Defaulted_Templated_NeedyTemplate8 > c2; + W_Defaulted_Templated_NeedyTemplate8 > c3; + W_Defaulted_Templated_NeedyTemplate8 > c4; + W_Defaulted_Templated_NeedyTemplate8 > c5; + W_Defaulted_Templated_NeedyTemplate8 > c6; + W_Defaulted_Templated_NeedyTemplate8 > c7; + W_Defaulted_Templated_NeedyTemplate8 > c8; + W_Defaulted_Templated_NeedyTemplate8 > c9; + W_Defaulted_Templated_NeedyTemplate8 > c10; + W_Defaulted_Templated_NeedyTemplate8 > c11; + W_Defaulted_Templated_NeedyTemplate8 > c12; +} + +void good8() { + W_Defaulted_Templated_NeedyTemplate8 a1; + W_Defaulted_Templated_NeedyTemplate8 a2; + W_Defaulted_Templated_NeedyTemplate8 a3; + W_Defaulted_Templated_NeedyTemplate8 a4; + W_Defaulted_Templated_NeedyTemplate8 a5; + W_Defaulted_Templated_NeedyTemplate8 a6; + + W_Defaulted_Templated_NeedyTemplate8 > b1; + W_Defaulted_Templated_NeedyTemplate8 > b2; + W_Defaulted_Templated_NeedyTemplate8 > b3; + W_Defaulted_Templated_NeedyTemplate8 > b4; + W_Defaulted_Templated_NeedyTemplate8 > b5; + W_Defaulted_Templated_NeedyTemplate8 > b6; + + W_Defaulted_Templated_NeedyTemplate8 > c1; + W_Defaulted_Templated_NeedyTemplate8 > c2; + W_Defaulted_Templated_NeedyTemplate8 > c3; + W_Defaulted_Templated_NeedyTemplate8 > c4; + W_Defaulted_Templated_NeedyTemplate8 > c5; + W_Defaulted_Templated_NeedyTemplate8 > c6; + W_Defaulted_Templated_NeedyTemplate8 > c7; + W_Defaulted_Templated_NeedyTemplate8 > c8; + W_Defaulted_Templated_NeedyTemplate8 > c9; + W_Defaulted_Templated_NeedyTemplate8 > c10; + W_Defaulted_Templated_NeedyTemplate8 > c11; + W_Defaulted_Templated_NeedyTemplate8 > c12; + + W_Defaulted_Templated_NeedyTemplate8 > d1; + W_Defaulted_Templated_NeedyTemplate8 > d2; + W_Defaulted_Templated_NeedyTemplate8 > d3; + W_Defaulted_Templated_NeedyTemplate8 > d4; + W_Defaulted_Templated_NeedyTemplate8 > d5; + W_Defaulted_Templated_NeedyTemplate8 > d6; + W_Defaulted_Templated_NeedyTemplate8 > d7; + W_Defaulted_Templated_NeedyTemplate8 > d8; + W_Defaulted_Templated_NeedyTemplate8 > d9; + W_Defaulted_Templated_NeedyTemplate8 > d10; + W_Defaulted_Templated_NeedyTemplate8 > d11; + W_Defaulted_Templated_NeedyTemplate8 > d12; +} + +/* + SpecializedNonMovable is a non-movable class which has an explicit specialization of NeedyTemplate + for it. Instantiations of NeedyTemplateN should be legal as the explicit + specialization isn't annotated with MOZ_NEEDS_MEMMOVABLE_TYPE. + + However, as it is MOZ_NON_MEMMOVABLE, derived classes and members shouldn't be able to be used to + instantiate NeedyTemplate. +*/ + +struct MOZ_NON_MEMMOVABLE SpecializedNonMovable {}; // expected-note 8 {{'S_SpecializedNonMovable' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'SpecializedNonMovable'}} expected-note 8 {{'Template_Inline' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'SpecializedNonMovable'}} +struct S_SpecializedNonMovable : SpecializedNonMovable {}; + +// Specialize all of the NeedyTemplates with SpecializedNonMovable. +template <> +struct NeedyTemplate1 {}; +template <> +struct NeedyTemplate2 {}; +template <> +struct NeedyTemplate3 {}; +template <> +struct NeedyTemplate4 {}; +template <> +struct NeedyTemplate5 {}; +template <> +struct NeedyTemplate6 {}; +template <> +struct NeedyTemplate7 {}; +template <> +struct NeedyTemplate8 {}; + +void specialization() { + /* + SpecializedNonMovable has a specialization for every variant of NeedyTemplate, + so these templates are valid, even though SpecializedNonMovable isn't + memmovable + */ + NeedyTemplate1 a1; + S_NeedyTemplate2 a2; + W_NeedyTemplate3 a3; + WS_NeedyTemplate4 a4; + SW_NeedyTemplate5 a5; + Defaulted_SW_NeedyTemplate6 a6; + Defaulted_Templated_NeedyTemplate7 a7; + W_Defaulted_Templated_NeedyTemplate8 a8; + + /* + These entries contain an element which is SpecializedNonMovable, and are non-movable + as there is no valid specialization, and their member is non-memmovable + */ + NeedyTemplate1 > b1; // expected-note {{instantiation of 'NeedyTemplate1 >' requested here}} + S_NeedyTemplate2 > b2; + W_NeedyTemplate3 > b3; + WS_NeedyTemplate4 > b4; + SW_NeedyTemplate5 > b5; + Defaulted_SW_NeedyTemplate6 > b6; + Defaulted_Templated_NeedyTemplate7 > b7; + W_Defaulted_Templated_NeedyTemplate8 > b8; + + /* + The subclass of SpecializedNonMovable, is also non-memmovable, + as there is no valid specialization. + */ + NeedyTemplate1 c1; // expected-note {{instantiation of 'NeedyTemplate1' requested here}} + S_NeedyTemplate2 c2; + W_NeedyTemplate3 c3; + WS_NeedyTemplate4 c4; + SW_NeedyTemplate5 c5; + Defaulted_SW_NeedyTemplate6 c6; + Defaulted_Templated_NeedyTemplate7 c7; + W_Defaulted_Templated_NeedyTemplate8 c8; +} diff --git a/build/clang-plugin/tests/TestStackClass.cpp b/build/clang-plugin/tests/TestStackClass.cpp index 6f01e384333..cb331176842 100644 --- a/build/clang-plugin/tests/TestStackClass.cpp +++ b/build/clang-plugin/tests/TestStackClass.cpp @@ -18,7 +18,7 @@ void misuseStackClass(int len) { Stack valid; Stack alsoValid[2]; static Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}} - static Stack alsoNotValid[2]; // expected-error {{variable of type 'Stack [2]' only valid on the stack}} + static Stack alsoNotValid[2]; // expected-error {{variable of type 'Stack [2]' only valid on the stack}} expected-note {{'Stack [2]' is a stack type because it is an array of stack type 'Stack'}} gobble(&valid); gobble(¬Valid); @@ -35,7 +35,7 @@ void misuseStackClass(int len) { Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}} struct RandomClass { - Stack nonstaticMember; // expected-note {{'RandomClass' is a stack class because member 'nonstaticMember' is a stack class 'Stack'}} + Stack nonstaticMember; // expected-note {{'RandomClass' is a stack type because member 'nonstaticMember' is a stack type 'Stack'}} static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}} }; struct MOZ_STACK_CLASS RandomStackClass { @@ -43,7 +43,7 @@ struct MOZ_STACK_CLASS RandomStackClass { static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}} }; -struct BadInherit : Stack {}; // expected-note {{'BadInherit' is a stack class because it inherits from a stack class 'Stack'}} +struct BadInherit : Stack {}; // expected-note {{'BadInherit' is a stack type because it inherits from a stack type 'Stack'}} struct MOZ_STACK_CLASS GoodInherit : Stack {}; BadInherit moreInvalid; // expected-error {{variable of type 'BadInherit' only valid on the stack}} diff --git a/build/clang-plugin/tests/moz.build b/build/clang-plugin/tests/moz.build index 6dc1ec98278..044ed31fc82 100644 --- a/build/clang-plugin/tests/moz.build +++ b/build/clang-plugin/tests/moz.build @@ -9,13 +9,16 @@ SOURCES += [ 'TestCustomHeap.cpp', 'TestExplicitOperatorBool.cpp', 'TestGlobalClass.cpp', + 'TestMultipleAnnotations.cpp', 'TestMustOverride.cpp', 'TestMustUse.cpp', 'TestNANTestingExpr.cpp', 'TestNANTestingExprC.c', + 'TestNeedsNoVTableType.cpp', 'TestNoAddRefReleaseOnReturn.cpp', 'TestNoArithmeticExprInArgument.cpp', 'TestNonHeapClass.cpp', + 'TestNonMemMovable.cpp', 'TestNoRefcountedInsideLambdas.cpp', 'TestStackClass.cpp', 'TestTrivialCtorDtor.cpp', diff --git a/build/valgrind/mach_commands.py b/build/valgrind/mach_commands.py index fb9e1f7db6c..b9038a2d8ef 100644 --- a/build/valgrind/mach_commands.py +++ b/build/valgrind/mach_commands.py @@ -109,6 +109,7 @@ class MachCommands(MachCommandBase): '--show-possibly-lost=no', '--track-origins=yes', '--trace-children=yes', + '-v', # Enable verbosity to get the list of used suppressions ] for s in suppressions: diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index e73e2722fe9..01c29640825 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -1710,20 +1710,22 @@ nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI, } uint32_t loadType = LOAD_NORMAL; + nsCOMPtr requestingPrincipal; if (aLoadInfo) { nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal; (void)aLoadInfo->GetLoadType(<); // Get the appropriate LoadType from nsIDocShellLoadInfo type loadType = ConvertDocShellLoadInfoToLoadType(lt); + + nsCOMPtr owner; + aLoadInfo->GetOwner(getter_AddRefs(owner)); + requestingPrincipal = do_QueryInterface(owner); } NS_ENSURE_SUCCESS(Stop(nsIWebNavigation::STOP_NETWORK), NS_ERROR_FAILURE); mLoadType = loadType; - nsCOMPtr owner; - aLoadInfo->GetOwner(getter_AddRefs(owner)); - nsCOMPtr requestingPrincipal = do_QueryInterface(owner); if (!requestingPrincipal) { requestingPrincipal = nsContentUtils::GetSystemPrincipal(); } @@ -2953,129 +2955,16 @@ nsDocShell::GetRecordProfileTimelineMarkers(bool* aValue) nsresult nsDocShell::PopProfileTimelineMarkers( JSContext* aCx, - JS::MutableHandle aProfileTimelineMarkers) + JS::MutableHandle aOut) { - // Looping over all markers gathered so far at the docShell level, whenever a - // START marker is found, look for the corresponding END marker and build a - // {name,start,end} JS object. - // Paint markers are different because paint is handled at root docShell level - // in the information that a paint was done is then stored at each sub - // docShell level but we can only be sure that a paint did happen in a - // docShell if an Layer marker type was recorded too. + nsTArray store; + SequenceRooter rooter(aCx, &store); - nsTArray profileTimelineMarkers; - SequenceRooter rooter( - aCx, &profileTimelineMarkers); - - if (!IsObserved()) { - if (!ToJSValue(aCx, profileTimelineMarkers, aProfileTimelineMarkers)) { - JS_ClearPendingException(aCx); - return NS_ERROR_UNEXPECTED; - } - return NS_OK; + if (IsObserved()) { + mObserved->PopMarkers(aCx, store); } - nsTArray>& markersStore = mObserved.get()->mTimelineMarkers; - - // If we see an unpaired START, we keep it around for the next call - // to PopProfileTimelineMarkers. We store the kept START objects in - // this array. - nsTArray> keptMarkers; - - for (uint32_t i = 0; i < markersStore.Length(); ++i) { - UniquePtr& startPayload = markersStore[i]; - const char* startMarkerName = startPayload->GetName(); - - bool hasSeenPaintedLayer = false; - bool isPaint = strcmp(startMarkerName, "Paint") == 0; - - // If we are processing a Paint marker, we append information from - // all the embedded Layer markers to this array. - dom::Sequence layerRectangles; - - // If this is a TRACING_TIMESTAMP marker, there's no corresponding "end" - // marker, as it's a single unit of time, not a duration, create the final - // marker here. - if (startPayload->GetMetaData() == TRACING_TIMESTAMP) { - mozilla::dom::ProfileTimelineMarker* marker = - profileTimelineMarkers.AppendElement(); - - marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName()); - marker->mStart = startPayload->GetTime(); - marker->mEnd = startPayload->GetTime(); - marker->mStack = startPayload->GetStack(); - startPayload->AddDetails(aCx, *marker); - continue; - } - - if (startPayload->GetMetaData() == TRACING_INTERVAL_START) { - bool hasSeenEnd = false; - - // DOM events can be nested, so we must take care when searching - // for the matching end. It doesn't hurt to apply this logic to - // all event types. - uint32_t markerDepth = 0; - - // The assumption is that the devtools timeline flushes markers frequently - // enough for the amount of markers to always be small enough that the - // nested for loop isn't going to be a performance problem. - for (uint32_t j = i + 1; j < markersStore.Length(); ++j) { - UniquePtr& endPayload = markersStore[j]; - const char* endMarkerName = endPayload->GetName(); - - // Look for Layer markers to stream out paint markers. - if (isPaint && strcmp(endMarkerName, "Layer") == 0) { - hasSeenPaintedLayer = true; - endPayload->AddLayerRectangles(layerRectangles); - } - - if (!startPayload->Equals(*endPayload)) { - continue; - } - - // Pair start and end markers. - if (endPayload->GetMetaData() == TRACING_INTERVAL_START) { - ++markerDepth; - } else if (endPayload->GetMetaData() == TRACING_INTERVAL_END) { - if (markerDepth > 0) { - --markerDepth; - } else { - // But ignore paint start/end if no layer has been painted. - if (!isPaint || (isPaint && hasSeenPaintedLayer)) { - mozilla::dom::ProfileTimelineMarker* marker = - profileTimelineMarkers.AppendElement(); - - marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName()); - marker->mStart = startPayload->GetTime(); - marker->mEnd = endPayload->GetTime(); - marker->mStack = startPayload->GetStack(); - if (isPaint) { - marker->mRectangles.Construct(layerRectangles); - } - startPayload->AddDetails(aCx, *marker); - endPayload->AddDetails(aCx, *marker); - } - - // We want the start to be dropped either way. - hasSeenEnd = true; - - break; - } - } - } - - // If we did not see the corresponding END, keep the START. - if (!hasSeenEnd) { - keptMarkers.AppendElement(Move(markersStore[i])); - markersStore.RemoveElementAt(i); - --i; - } - } - } - - markersStore.SwapElements(keptMarkers); - - if (!ToJSValue(aCx, profileTimelineMarkers, aProfileTimelineMarkers)) { + if (!ToJSValue(aCx, store, aOut)) { JS_ClearPendingException(aCx); return NS_ERROR_UNEXPECTED; } diff --git a/docshell/base/timeline/ObservedDocShell.cpp b/docshell/base/timeline/ObservedDocShell.cpp index d2c352ed236..613ca93d623 100644 --- a/docshell/base/timeline/ObservedDocShell.cpp +++ b/docshell/base/timeline/ObservedDocShell.cpp @@ -34,4 +34,101 @@ ObservedDocShell::ClearMarkers() mTimelineMarkers.Clear(); } +void +ObservedDocShell::PopMarkers(JSContext* aCx, + nsTArray& aStore) +{ + // If we see an unpaired START, we keep it around for the next call + // to ObservedDocShell::PopMarkers. We store the kept START objects here. + nsTArray> keptStartMarkers; + + for (uint32_t i = 0; i < mTimelineMarkers.Length(); ++i) { + UniquePtr& startPayload = mTimelineMarkers[i]; + + // If this is a TRACING_TIMESTAMP marker, there's no corresponding END + // as it's a single unit of time, not a duration. + if (startPayload->GetMetaData() == TRACING_TIMESTAMP) { + dom::ProfileTimelineMarker* marker = aStore.AppendElement(); + marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName()); + marker->mStart = startPayload->GetTime(); + marker->mEnd = startPayload->GetTime(); + marker->mStack = startPayload->GetStack(); + startPayload->AddDetails(aCx, *marker); + continue; + } + + // Whenever a START marker is found, look for the corresponding END + // and build a {name,start,end} JS object. + if (startPayload->GetMetaData() == TRACING_INTERVAL_START) { + bool hasSeenEnd = false; + + // "Paint" markers are different because painting is handled at root + // docshell level. The information that a paint was done is stored at + // sub-docshell level, but we can only be sure that a paint did actually + // happen in if a "Layer" marker was recorded too. + bool startIsPaintType = strcmp(startPayload->GetName(), "Paint") == 0; + bool hasSeenLayerType = false; + + // If we are processing a "Paint" marker, we append information from + // all the embedded "Layer" markers to this array. + dom::Sequence layerRectangles; + + // DOM events can be nested, so we must take care when searching + // for the matching end. It doesn't hurt to apply this logic to + // all event types. + uint32_t markerDepth = 0; + + // The assumption is that the devtools timeline flushes markers frequently + // enough for the amount of markers to always be small enough that the + // nested for loop isn't going to be a performance problem. + for (uint32_t j = i + 1; j < mTimelineMarkers.Length(); ++j) { + UniquePtr& endPayload = mTimelineMarkers[j]; + bool endIsLayerType = strcmp(endPayload->GetName(), "Layer") == 0; + + // Look for "Layer" markers to stream out "Paint" markers. + if (startIsPaintType && endIsLayerType) { + hasSeenLayerType = true; + endPayload->AddLayerRectangles(layerRectangles); + } + if (!startPayload->Equals(*endPayload)) { + continue; + } + if (endPayload->GetMetaData() == TRACING_INTERVAL_START) { + ++markerDepth; + continue; + } + if (endPayload->GetMetaData() == TRACING_INTERVAL_END) { + if (markerDepth > 0) { + --markerDepth; + continue; + } + if (!startIsPaintType || (startIsPaintType && hasSeenLayerType)) { + dom::ProfileTimelineMarker* marker = aStore.AppendElement(); + marker->mName = NS_ConvertUTF8toUTF16(startPayload->GetName()); + marker->mStart = startPayload->GetTime(); + marker->mEnd = endPayload->GetTime(); + marker->mStack = startPayload->GetStack(); + if (hasSeenLayerType) { + marker->mRectangles.Construct(layerRectangles); + } + startPayload->AddDetails(aCx, *marker); + endPayload->AddDetails(aCx, *marker); + } + hasSeenEnd = true; + break; + } + } + + // If we did not see the corresponding END, keep the START. + if (!hasSeenEnd) { + keptStartMarkers.AppendElement(Move(mTimelineMarkers[i])); + mTimelineMarkers.RemoveElementAt(i); + --i; + } + } + } + + mTimelineMarkers.SwapElements(keptStartMarkers); +} + } // namespace mozilla diff --git a/docshell/base/timeline/ObservedDocShell.h b/docshell/base/timeline/ObservedDocShell.h index 10b1567351c..1bcab4023dc 100644 --- a/docshell/base/timeline/ObservedDocShell.h +++ b/docshell/base/timeline/ObservedDocShell.h @@ -15,6 +15,9 @@ class nsDocShell; class TimelineMarker; namespace mozilla { +namespace dom { +struct ProfileTimelineMarker; +} // # ObservedDocShell // @@ -24,18 +27,16 @@ class ObservedDocShell : public LinkedListElement { private: nsRefPtr mDocShell; - -public: - // FIXME: make this private once all marker-specific logic has been - // moved out of nsDocShell. nsTArray> mTimelineMarkers; +public: explicit ObservedDocShell(nsDocShell* aDocShell); nsDocShell* operator*() const { return mDocShell.get(); } void AddMarker(const char* aName, TracingMetadata aMetaData); void AddMarker(UniquePtr&& aMarker); void ClearMarkers(); + void PopMarkers(JSContext* aCx, nsTArray& aStore); }; } // namespace mozilla diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index c5fc2e6a4b8..a35f8640423 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -2728,8 +2728,52 @@ Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem, const Optional>& aOptions, ErrorResult& aRv) { + nsAutoCString logMsg; + logMsg.AppendPrintf("Navigator::RequestMediaKeySystemAccess(keySystem='%s' options=[", + NS_ConvertUTF16toUTF8(aKeySystem).get()); + if (aOptions.WasPassed()) { + const Sequence& options = aOptions.Value(); + for (size_t i = 0; i < options.Length(); i++) { + const MediaKeySystemOptions& op = options[i]; + if (i > 0) { + logMsg.AppendLiteral(","); + } + logMsg.AppendLiteral("{"); + logMsg.AppendPrintf("stateful='%s'", + MediaKeysRequirementValues::strings[(size_t)op.mStateful].value); + + logMsg.AppendPrintf(", uniqueIdentifier='%s'", + MediaKeysRequirementValues::strings[(size_t)op.mUniqueidentifier].value); + + if (!op.mAudioCapability.IsEmpty()) { + logMsg.AppendPrintf(", audioCapability='%s'", + NS_ConvertUTF16toUTF8(op.mAudioCapability).get()); + } + if (!op.mAudioType.IsEmpty()) { + logMsg.AppendPrintf(", audioType='%s'", + NS_ConvertUTF16toUTF8(op.mAudioType).get()); + } + if (!op.mInitDataType.IsEmpty()) { + logMsg.AppendPrintf(", initDataType='%s'", + NS_ConvertUTF16toUTF8(op.mInitDataType).get()); + } + if (!op.mVideoCapability.IsEmpty()) { + logMsg.AppendPrintf(", videoCapability='%s'", + NS_ConvertUTF16toUTF8(op.mVideoCapability).get()); + } + if (!op.mVideoType.IsEmpty()) { + logMsg.AppendPrintf(", videoType='%s'", + NS_ConvertUTF16toUTF8(op.mVideoType).get()); + } + logMsg.AppendLiteral("}"); + } + } + logMsg.AppendPrintf("])"); + EME_LOG(logMsg.get()); + nsCOMPtr go = do_QueryInterface(mWindow); - nsRefPtr promise = DetailedPromise::Create(go, aRv); + nsRefPtr promise = DetailedPromise::Create(go, aRv, + NS_LITERAL_CSTRING("navigator.requestMediaKeySystemAccess")); if (aRv.Failed()) { return nullptr; } diff --git a/dom/base/nsMimeTypeArray.cpp b/dom/base/nsMimeTypeArray.cpp index ca3531b61fe..0ae20aeba05 100644 --- a/dom/base/nsMimeTypeArray.cpp +++ b/dom/base/nsMimeTypeArray.cpp @@ -9,11 +9,13 @@ #include "mozilla/dom/MimeTypeArrayBinding.h" #include "mozilla/dom/MimeTypeBinding.h" #include "nsIDOMNavigator.h" +#include "nsPIDOMWindow.h" #include "nsPluginArray.h" #include "nsIMIMEService.h" #include "nsIMIMEInfo.h" #include "Navigator.h" #include "nsServiceManagerUtils.h" +#include "nsPluginTags.h" using namespace mozilla; using namespace mozilla::dom; @@ -216,19 +218,22 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsMimeType, Release) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsMimeType, mWindow, mPluginElement) -nsMimeType::nsMimeType(nsPIDOMWindow* aWindow, nsPluginElement* aPluginElement, - uint32_t aPluginTagMimeIndex, const nsAString& aType) +nsMimeType::nsMimeType(nsPIDOMWindow* aWindow, + nsPluginElement* aPluginElement, + const nsAString& aType, + const nsAString& aDescription, + const nsAString& aExtension) : mWindow(aWindow), mPluginElement(aPluginElement), - mPluginTagMimeIndex(aPluginTagMimeIndex), - mType(aType) + mType(aType), + mDescription(aDescription), + mExtension(aExtension) { } nsMimeType::nsMimeType(nsPIDOMWindow* aWindow, const nsAString& aType) : mWindow(aWindow), mPluginElement(nullptr), - mPluginTagMimeIndex(0), mType(aType) { } @@ -251,14 +256,9 @@ nsMimeType::WrapObject(JSContext* aCx, JS::Handle aGivenProto) } void -nsMimeType::GetDescription(nsString& retval) const +nsMimeType::GetDescription(nsString& aRetval) const { - retval.Truncate(); - - if (mPluginElement) { - CopyUTF8toUTF16(mPluginElement->PluginTag()-> - mMimeDescriptions[mPluginTagMimeIndex], retval); - } + aRetval = mDescription; } nsPluginElement* @@ -269,14 +269,9 @@ nsMimeType::GetEnabledPlugin() const } void -nsMimeType::GetSuffixes(nsString& retval) const +nsMimeType::GetSuffixes(nsString& aRetval) const { - retval.Truncate(); - - if (mPluginElement) { - CopyUTF8toUTF16(mPluginElement->PluginTag()-> - mExtensions[mPluginTagMimeIndex], retval); - } + aRetval = mExtension; } void diff --git a/dom/base/nsMimeTypeArray.h b/dom/base/nsMimeTypeArray.h index 6ca5505c76c..1e22fcd7e81 100644 --- a/dom/base/nsMimeTypeArray.h +++ b/dom/base/nsMimeTypeArray.h @@ -58,8 +58,11 @@ public: NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsMimeType) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsMimeType) - nsMimeType(nsPIDOMWindow* aWindow, nsPluginElement* aPluginElement, - uint32_t aPluginTagMimeIndex, const nsAString& aMimeType); + nsMimeType(nsPIDOMWindow* aWindow, + nsPluginElement* aPluginElement, + const nsAString& aType, + const nsAString& aDescription, + const nsAString& aExtension); nsMimeType(nsPIDOMWindow* aWindow, const nsAString& aMimeType); nsPIDOMWindow* GetParentObject() const; virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; @@ -85,8 +88,9 @@ protected: // mimetype array. We rely on the cycle collector to break this // cycle. nsRefPtr mPluginElement; - uint32_t mPluginTagMimeIndex; nsString mType; + nsString mDescription; + nsString mExtension; }; #endif /* nsMimeTypeArray_h___ */ diff --git a/dom/base/nsPluginArray.cpp b/dom/base/nsPluginArray.cpp index d8391e5451f..c0bd8d46e2d 100644 --- a/dom/base/nsPluginArray.cpp +++ b/dom/base/nsPluginArray.cpp @@ -130,7 +130,7 @@ nsPluginArray::Refresh(bool aReloadDocuments) // that plugins did not change and was not reloaded if (pluginHost->ReloadPlugins() == NS_ERROR_PLUGINS_PLUGINSNOTCHANGED) { - nsTArray > newPluginTags; + nsTArray > newPluginTags; pluginHost->GetPlugins(newPluginTags); // Check if the number of plugins we know about are different from @@ -279,7 +279,7 @@ operator<(const nsRefPtr& lhs, const nsRefPtr& rhs) { // Sort plugins alphabetically by name. - return lhs->PluginTag()->mName < rhs->PluginTag()->mName; + return lhs->PluginTag()->Name() < rhs->PluginTag()->Name(); } void @@ -296,14 +296,13 @@ nsPluginArray::EnsurePlugins() return; } - nsTArray > pluginTags; + nsTArray > pluginTags; pluginHost->GetPlugins(pluginTags); // need to wrap each of these with a nsPluginElement, which is // scriptable. for (uint32_t i = 0; i < pluginTags.Length(); ++i) { - nsPluginTag* pluginTag = pluginTags[i]; - mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTag)); + mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i])); } // Alphabetize the enumeration order of non-hidden plugins to reduce @@ -323,7 +322,7 @@ NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPluginElement, mWindow, mMimeTypes) nsPluginElement::nsPluginElement(nsPIDOMWindow* aWindow, - nsPluginTag* aPluginTag) + nsIInternalPluginTag* aPluginTag) : mWindow(aWindow), mPluginTag(aPluginTag) { @@ -349,25 +348,25 @@ nsPluginElement::WrapObject(JSContext* aCx, JS::Handle aGivenProto) void nsPluginElement::GetDescription(nsString& retval) const { - CopyUTF8toUTF16(mPluginTag->mDescription, retval); + CopyUTF8toUTF16(mPluginTag->Description(), retval); } void nsPluginElement::GetFilename(nsString& retval) const { - CopyUTF8toUTF16(mPluginTag->mFileName, retval); + CopyUTF8toUTF16(mPluginTag->FileName(), retval); } void nsPluginElement::GetVersion(nsString& retval) const { - CopyUTF8toUTF16(mPluginTag->mVersion, retval); + CopyUTF8toUTF16(mPluginTag->Version(), retval); } void nsPluginElement::GetName(nsString& retval) const { - CopyUTF8toUTF16(mPluginTag->mName, retval); + CopyUTF8toUTF16(mPluginTag->Name(), retval); } nsMimeType* @@ -452,8 +451,18 @@ nsPluginElement::EnsurePluginMimeTypes() return; } - for (uint32_t i = 0; i < mPluginTag->mMimeTypes.Length(); ++i) { - NS_ConvertUTF8toUTF16 type(mPluginTag->mMimeTypes[i]); - mMimeTypes.AppendElement(new nsMimeType(mWindow, this, i, type)); + if (mPluginTag->MimeTypes().Length() != mPluginTag->MimeDescriptions().Length() || + mPluginTag->MimeTypes().Length() != mPluginTag->Extensions().Length()) { + MOZ_ASSERT(false, "mime type arrays expected to be the same length"); + return; + } + + for (uint32_t i = 0; i < mPluginTag->MimeTypes().Length(); ++i) { + NS_ConvertUTF8toUTF16 type(mPluginTag->MimeTypes()[i]); + NS_ConvertUTF8toUTF16 description(mPluginTag->MimeDescriptions()[i]); + NS_ConvertUTF8toUTF16 extension(mPluginTag->Extensions()[i]); + + mMimeTypes.AppendElement(new nsMimeType(mWindow, this, type, description, + extension)); } } diff --git a/dom/base/nsPluginArray.h b/dom/base/nsPluginArray.h index 2ae47627067..f73f50511b9 100644 --- a/dom/base/nsPluginArray.h +++ b/dom/base/nsPluginArray.h @@ -11,11 +11,11 @@ #include "nsWeakReference.h" #include "nsIObserver.h" #include "nsWrapperCache.h" -#include "nsPluginTags.h" #include "nsPIDOMWindow.h" class nsPluginElement; class nsMimeType; +class nsIInternalPluginTag; class nsPluginArray final : public nsIObserver, public nsSupportsWeakReference, @@ -70,12 +70,12 @@ public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPluginElement) - nsPluginElement(nsPIDOMWindow* aWindow, nsPluginTag* aPluginTag); + nsPluginElement(nsPIDOMWindow* aWindow, nsIInternalPluginTag* aPluginTag); nsPIDOMWindow* GetParentObject() const; virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - nsPluginTag* PluginTag() const + nsIInternalPluginTag* PluginTag() const { return mPluginTag; } @@ -102,7 +102,7 @@ protected: void EnsurePluginMimeTypes(); nsCOMPtr mWindow; - nsRefPtr mPluginTag; + nsCOMPtr mPluginTag; nsTArray > mMimeTypes; }; diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index f98d6df2fef..78480ef0c77 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -960,6 +960,25 @@ DOMInterfaces = { 'workers': True }, +'PushManager': [{ + 'workers': False, + 'headerFile': 'mozilla/dom/PushManager.h', + 'nativeType': 'mozilla::dom::PushManager', +}, { + 'workers': True, + 'headerFile': 'mozilla/dom/PushManager.h', + 'nativeType': 'mozilla::dom::WorkerPushManager', +}], + +'PushSubscription': [{ + 'workers': False, + 'headerFile': 'mozilla/dom/PushManager.h', +}, { + 'workers': True, + 'headerFile': 'mozilla/dom/PushManager.h', + 'nativeType': 'mozilla::dom::WorkerPushSubscription', +}], + 'Range': { 'nativeType': 'nsRange', 'binaryNames': { diff --git a/dom/broadcastchannel/BroadcastChannel.cpp b/dom/broadcastchannel/BroadcastChannel.cpp index b6331473c67..b3547da485c 100644 --- a/dom/broadcastchannel/BroadcastChannel.cpp +++ b/dom/broadcastchannel/BroadcastChannel.cpp @@ -12,7 +12,6 @@ #include "mozilla/ipc/BackgroundChild.h" #include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/ipc/PBackgroundChild.h" -#include "mozilla/Preferences.h" #include "WorkerPrivate.h" #include "WorkerRunnable.h" @@ -299,50 +298,8 @@ private: } }; -class PrefEnabledRunnable final : public WorkerMainThreadRunnable -{ -public: - explicit PrefEnabledRunnable(WorkerPrivate* aWorkerPrivate) - : WorkerMainThreadRunnable(aWorkerPrivate) - , mEnabled(false) - { } - - bool MainThreadRun() override - { - AssertIsOnMainThread(); - mEnabled = Preferences::GetBool("dom.broadcastChannel.enabled", false); - return true; - } - - bool IsEnabled() const - { - return mEnabled; - } - -private: - bool mEnabled; -}; - } // namespace -/* static */ bool -BroadcastChannel::IsEnabled(JSContext* aCx, JSObject* aGlobal) -{ - if (NS_IsMainThread()) { - return Preferences::GetBool("dom.broadcastChannel.enabled", false); - } - - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(workerPrivate); - workerPrivate->AssertIsOnWorkerThread(); - - nsRefPtr runnable = - new PrefEnabledRunnable(workerPrivate); - runnable->Dispatch(workerPrivate->GetJSContext()); - - return runnable->IsEnabled(); -} - BroadcastChannel::BroadcastChannel(nsPIDOMWindow* aWindow, const PrincipalInfo& aPrincipalInfo, const nsACString& aOrigin, diff --git a/dom/broadcastchannel/BroadcastChannel.h b/dom/broadcastchannel/BroadcastChannel.h index 65af55e7695..a22fa0b2a60 100644 --- a/dom/broadcastchannel/BroadcastChannel.h +++ b/dom/broadcastchannel/BroadcastChannel.h @@ -47,8 +47,6 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BroadcastChannel, DOMEventTargetHelper) - static bool IsEnabled(JSContext* aCx, JSObject* aGlobal); - virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; diff --git a/dom/broadcastchannel/tests/broadcastchannel_pref_worker.js b/dom/broadcastchannel/tests/broadcastchannel_pref_worker.js deleted file mode 100644 index 639d8e258fc..00000000000 --- a/dom/broadcastchannel/tests/broadcastchannel_pref_worker.js +++ /dev/null @@ -1,11 +0,0 @@ -onmessage = function() { - var exists = true; - try { - var bc = new BroadcastChannel('foobar'); - } catch(e) { - exists = false; - } - - postMessage({ exists: exists }); -} - diff --git a/dom/broadcastchannel/tests/mochitest.ini b/dom/broadcastchannel/tests/mochitest.ini index 8ba17d77cfd..0be255e4bcc 100644 --- a/dom/broadcastchannel/tests/mochitest.ini +++ b/dom/broadcastchannel/tests/mochitest.ini @@ -1,7 +1,6 @@ [DEFAULT] support-files = iframe_broadcastchannel.html - broadcastchannel_pref_worker.js broadcastchannel_sharedWorker.js broadcastchannel_worker.js broadcastchannel_worker_alive.js @@ -17,7 +16,6 @@ support-files = [test_broadcastchannel_basic.html] [test_broadcastchannel_close.html] [test_broadcastchannel_self.html] -[test_broadcastchannel_pref.html] [test_broadcastchannel_sharedWorker.html] [test_broadcastchannel_worker.html] [test_broadcastchannel_worker_alive.html] diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_any.html b/dom/broadcastchannel/tests/test_broadcastchannel_any.html index 38535ce1474..2225e7cad9a 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_any.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_any.html @@ -130,7 +130,7 @@ function runTest() { } SimpleTest.waitForExplicitFinish(); -SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest); +runTest(); diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_basic.html b/dom/broadcastchannel/tests/test_broadcastchannel_basic.html index eeb74813812..6aecf6c048b 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_basic.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_basic.html @@ -55,7 +55,7 @@ function runTest() { } SimpleTest.waitForExplicitFinish(); -SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest); +runTest(); diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_close.html b/dom/broadcastchannel/tests/test_broadcastchannel_close.html index 430e13de75d..84d41db4f94 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_close.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_close.html @@ -54,7 +54,7 @@ function runTest() { } SimpleTest.waitForExplicitFinish(); -SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest); +runTest(); diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser.html b/dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser.html index f5748bc8f49..180bd72e5be 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser.html @@ -84,8 +84,7 @@ var steps = [ }, function() { - SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true], - ["network.disable.ipc.security", true], + SpecialPowers.pushPrefEnv({"set": [["network.disable.ipc.security", true], ["browser.pagethumbnails.capturing_disabled", true], ["dom.mozBrowserFramesEnabled", true], ["dom.ipc.browser_frames.oop_by_default", false], diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser2.html b/dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser2.html index 52a0a15ff46..4bdaaf3b3e1 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser2.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_mozbrowser2.html @@ -84,8 +84,7 @@ var steps = [ }, function() { - SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true], - ["network.disable.ipc.security", true], + SpecialPowers.pushPrefEnv({"set": [["network.disable.ipc.security", true], ["browser.pagethumbnails.capturing_disabled", true], ["dom.mozBrowserFramesEnabled", true], ["dom.ipc.browser_frames.oop_by_default", false], diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_pref.html b/dom/broadcastchannel/tests/test_broadcastchannel_pref.html deleted file mode 100644 index 9b3dd51f718..00000000000 --- a/dom/broadcastchannel/tests/test_broadcastchannel_pref.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - Test for BroadcastChannel - - - - - -
- - - - diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_private_browsing.html b/dom/broadcastchannel/tests/test_broadcastchannel_private_browsing.html index 9c89f45ca76..eb4d2e3709f 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_private_browsing.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_private_browsing.html @@ -109,7 +109,7 @@ function runTest() { } SimpleTest.waitForExplicitFinish(); -SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest); +runTest(); diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_self.html b/dom/broadcastchannel/tests/test_broadcastchannel_self.html index 09597b4d956..32df390be1b 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_self.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_self.html @@ -30,7 +30,7 @@ function runTest() { } SimpleTest.waitForExplicitFinish(); -SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest); +runTest(); diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_sharedWorker.html b/dom/broadcastchannel/tests/test_broadcastchannel_sharedWorker.html index 4cd88c1f41a..c56be7e698f 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_sharedWorker.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_sharedWorker.html @@ -44,8 +44,7 @@ function runTests() { } SimpleTest.waitForExplicitFinish(); -SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true], - ["dom.workers.sharedWorkers.enabled", true]]}, runTests); +SpecialPowers.pushPrefEnv({"set": [["dom.workers.sharedWorkers.enabled", true]]}, runTests); diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_worker.html b/dom/broadcastchannel/tests/test_broadcastchannel_worker.html index 6f731eb7a0f..42e93cc1e10 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_worker.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_worker.html @@ -54,7 +54,7 @@ function runTests() { } SimpleTest.waitForExplicitFinish(); -SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTests); +runTests(); diff --git a/dom/broadcastchannel/tests/test_broadcastchannel_worker_alive.html b/dom/broadcastchannel/tests/test_broadcastchannel_worker_alive.html index 340431b3cef..8b1b03c4e7e 100644 --- a/dom/broadcastchannel/tests/test_broadcastchannel_worker_alive.html +++ b/dom/broadcastchannel/tests/test_broadcastchannel_worker_alive.html @@ -48,7 +48,7 @@ function runTests() { } SimpleTest.waitForExplicitFinish(); -SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTests); +runTests(); diff --git a/dom/browser-element/BrowserElementChild.js b/dom/browser-element/BrowserElementChild.js index 653c5de604c..ea25ce968de 100644 --- a/dom/browser-element/BrowserElementChild.js +++ b/dom/browser-element/BrowserElementChild.js @@ -41,7 +41,15 @@ if (!('BrowserElementIsPreloaded' in this)) { } catch (e) { } } + } + if(Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) { + // general content apps + if (isTopBrowserElement(docShell)) { + Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js"); + } + } else { + // rocketbar in system app and other in-process case (ex. B2G desktop client) Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js"); } diff --git a/dom/browser-element/BrowserElementCopyPaste.js b/dom/browser-element/BrowserElementCopyPaste.js index bfe4f71bc2f..ae5a8f091bf 100644 --- a/dom/browser-element/BrowserElementCopyPaste.js +++ b/dom/browser-element/BrowserElementCopyPaste.js @@ -8,6 +8,8 @@ dump("###################################### BrowserElementCopyPaste.js loaded\n"); +let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; + let CopyPasteAssistent = { COMMAND_MAP: { 'cut': 'cmd_cut', @@ -81,6 +83,13 @@ let CopyPasteAssistent = { detail.rect.left += currentRect.left; detail.rect.right += currentRect.left; currentWindow = currentWindow.realFrameElement.ownerDocument.defaultView; + + let targetDocShell = currentWindow + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation); + if(targetDocShell.isBrowserOrApp) { + break; + } } sendAsyncMsg('caretstatechanged', detail); diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index eaf781e76df..28afb83eda0 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -5031,21 +5031,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx, return NS_ERROR_DOM_SYNTAX_ERR; } - IntRect srcRect(0, 0, mWidth, mHeight); - IntRect destRect(aX, aY, aWidth, aHeight); - IntRect srcReadRect = srcRect.Intersect(destRect); - RefPtr readback; - DataSourceSurface::MappedSurface rawData; - if (!srcReadRect.IsEmpty() && !mZero) { - RefPtr snapshot = mTarget->Snapshot(); - if (snapshot) { - readback = snapshot->GetDataSurface(); - } - if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) { - return NS_ERROR_OUT_OF_MEMORY; - } - } - JS::Rooted darray(aCx, JS_NewUint8ClampedArray(aCx, len.value())); if (!darray) { return NS_ERROR_OUT_OF_MEMORY; @@ -5056,6 +5041,21 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx, return NS_OK; } + IntRect srcRect(0, 0, mWidth, mHeight); + IntRect destRect(aX, aY, aWidth, aHeight); + IntRect srcReadRect = srcRect.Intersect(destRect); + RefPtr readback; + DataSourceSurface::MappedSurface rawData; + if (!srcReadRect.IsEmpty()) { + RefPtr snapshot = mTarget->Snapshot(); + if (snapshot) { + readback = snapshot->GetDataSurface(); + } + if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + IntRect dstWriteRect = srcReadRect; dstWriteRect.MoveBy(-aX, -aY); @@ -5074,10 +5074,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx, srcStride = aWidth * 4; } - // NOTE! dst is the same as src, and this relies on reading - // from src and advancing that ptr before writing to dst. - // NOTE! I'm not sure that it is, I think this comment might have been - // inherited from Thebes canvas and is no longer true uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4; if (mOpaque) { diff --git a/dom/canvas/WebGLTexelConversions.h b/dom/canvas/WebGLTexelConversions.h index 9eadb14e2d9..3371f542716 100644 --- a/dom/canvas/WebGLTexelConversions.h +++ b/dom/canvas/WebGLTexelConversions.h @@ -804,6 +804,15 @@ pack MOZ_ALWAYS_INLINE void +pack(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = src[0] * scaleFactor; + dst[1] = src[1] * scaleFactor; + dst[2] = src[2] * scaleFactor; +} + template<> MOZ_ALWAYS_INLINE void pack(const float* __restrict src, float* __restrict dst) { @@ -826,11 +835,11 @@ pack MOZ_ALWAYS_INLINE void pack(const float* __restrict src, float* __restrict dst) { - float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; - dst[0] = src[0] * scaleFactor; - dst[1] = src[1] * scaleFactor; - dst[2] = src[2] * scaleFactor; - dst[3] = src[3]; + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = src[0] * scaleFactor; + dst[1] = src[1] * scaleFactor; + dst[2] = src[2] * scaleFactor; + dst[3] = src[3]; } template<> MOZ_ALWAYS_INLINE void @@ -845,6 +854,12 @@ pack MOZ_ALWAYS_INLINE void +pack(const float* __restrict src, float* __restrict dst) +{ + dst[0] = src[3]; +} + template<> MOZ_ALWAYS_INLINE void pack(const float* __restrict src, float* __restrict dst) { @@ -858,6 +873,13 @@ pack MOZ_ALWAYS_INLINE void +pack(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = src[0] * scaleFactor; +} + template<> MOZ_ALWAYS_INLINE void pack(const float* __restrict src, float* __restrict dst) { @@ -873,6 +895,14 @@ pack MOZ_ALWAYS_INLINE void +pack(const float* __restrict src, float* __restrict dst) +{ + float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f; + dst[0] = src[0] * scaleFactor; + dst[1] = src[3]; +} + template<> MOZ_ALWAYS_INLINE void pack(const uint16_t* __restrict src, uint16_t* __restrict dst) { @@ -890,6 +920,16 @@ pack MOZ_ALWAYS_INLINE void +pack(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float unpackedAlpha = unpackFromFloat16(src[3]); + float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f; + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); + dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor); +} + template<> MOZ_ALWAYS_INLINE void pack(const uint16_t* __restrict src, uint16_t* __restrict dst) { @@ -909,6 +949,17 @@ pack MOZ_ALWAYS_INLINE void +pack(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float unpackedAlpha = unpackFromFloat16(src[3]); + float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f; + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor); + dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor); + dst[3] = src[3]; +} + template<> MOZ_ALWAYS_INLINE void pack(const uint16_t* __restrict src, uint16_t* __restrict dst) { @@ -921,6 +972,12 @@ pack MOZ_ALWAYS_INLINE void +pack(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + dst[0] = src[3]; +} + template<> MOZ_ALWAYS_INLINE void pack(const uint16_t* __restrict src, uint16_t* __restrict dst) { @@ -934,6 +991,14 @@ pack MOZ_ALWAYS_INLINE void +pack(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float unpackedAlpha = unpackFromFloat16(src[3]); + float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f; + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); +} + template<> MOZ_ALWAYS_INLINE void pack(const uint16_t* __restrict src, uint16_t* __restrict dst) { @@ -949,6 +1014,15 @@ pack MOZ_ALWAYS_INLINE void +pack(const uint16_t* __restrict src, uint16_t* __restrict dst) +{ + float unpackedAlpha = unpackFromFloat16(src[3]); + float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f; + dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor); + dst[1] = src[3]; +} + /****** END CODE SHARED WITH WEBKIT ******/ template MOZ_ALWAYS_INLINE void diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 493bbd26678..432dba7573d 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -4561,7 +4561,8 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys, aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } - nsRefPtr promise = DetailedPromise::Create(global, aRv); + nsRefPtr promise = DetailedPromise::Create(global, aRv, + NS_LITERAL_CSTRING("HTMLMediaElement.setMediaKeys")); if (aRv.Failed()) { return nullptr; } diff --git a/dom/html/HTMLTrackElement.cpp b/dom/html/HTMLTrackElement.cpp index 1c0276aa2d0..bd375fb5eef 100644 --- a/dom/html/HTMLTrackElement.cpp +++ b/dom/html/HTMLTrackElement.cpp @@ -203,26 +203,6 @@ HTMLTrackElement::LoadResource() mChannel = nullptr; } - rv = nsContentUtils::GetSecurityManager()-> - CheckLoadURIWithPrincipal(NodePrincipal(), uri, - nsIScriptSecurityManager::STANDARD); - NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); - - int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_TRACK, - uri, - NodePrincipal(), - static_cast(this), - NS_LITERAL_CSTRING("text/vtt"), // mime type - nullptr, // extra - &shouldLoad, - nsContentUtils::GetContentPolicy(), - nsContentUtils::GetSecurityManager()); - NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); - if (NS_CP_REJECTED(shouldLoad)) { - return; - } - // We may already have a TextTrack at this point if GetTrack() has already // been called. This happens, for instance, if script tries to get the // TextTrack before its mTrackElement has been bound to the DOM tree. @@ -235,7 +215,7 @@ HTMLTrackElement::LoadResource() rv = NS_NewChannel(getter_AddRefs(channel), uri, static_cast(this), - nsILoadInfo::SEC_NORMAL, + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS, nsIContentPolicy::TYPE_INTERNAL_TRACK, loadGroup); @@ -247,7 +227,7 @@ HTMLTrackElement::LoadResource() channel->SetNotificationCallbacks(mListener); LOG(LogLevel::Debug, ("opening webvtt channel")); - rv = channel->AsyncOpen(mListener, nullptr); + rv = channel->AsyncOpen2(mListener); NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv)); mChannel = channel; diff --git a/dom/interfaces/push/moz.build b/dom/interfaces/push/moz.build index 879a078c165..541fd1af53f 100644 --- a/dom/interfaces/push/moz.build +++ b/dom/interfaces/push/moz.build @@ -5,6 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. XPIDL_SOURCES += [ + 'nsIPushClient.idl', 'nsIPushNotificationService.idl', 'nsIPushObserverNotification.idl', ] diff --git a/dom/interfaces/push/nsIPushClient.idl b/dom/interfaces/push/nsIPushClient.idl new file mode 100644 index 00000000000..5c9bdf627e2 --- /dev/null +++ b/dom/interfaces/push/nsIPushClient.idl @@ -0,0 +1,53 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIPrincipal; + +/** + * Satisfies contracts similar to the Push API specification. + * + * If status is not NS_OK, endpoint should be ignored. When subscribing to + * a new endpoint, endpoint will be a valid URL on success, when querying for + * the presence of an existing subscription, this will be an empty string if + * the calling {scope+principal} does not currently have an associated + * endpoint. + */ + +[scriptable, uuid(0bcac389-a3ac-44a4-97fb-b50e41a46146)] +interface nsIPushEndpointCallback : nsISupports +{ + void onPushEndpoint(in nsresult status, in DOMString endpoint); +}; + +/** + * Satisfies contracts similar to the Push API specification. + * + * If status is not NS_OK, there was a problem unsubscribing and success should + * be ignored. success is true if unsubscribing was successful and false if + * there was no subscription. + */ +[scriptable, uuid(9522934d-e844-4f2f-81e8-48c3947b44de)] +interface nsIUnsubscribeResultCallback : nsISupports +{ + void onUnsubscribe(in nsresult status, in bool success); +}; + +/** + * Provides an XPIDL component to interact with the PushService from content + * processes. Unlike PushManager, this has no relationship to the DOM and is + * not exposed to web content. This was added to allow ServiceWorkers to use + * it by dispatching appropriate runnables to the main thread. + */ +[scriptable, uuid(6622d599-439e-4ad1-af32-c941bd2b9968)] +interface nsIPushClient : nsISupports +{ + void subscribe(in DOMString scope, in nsIPrincipal principal, in nsIPushEndpointCallback callback); + + void unsubscribe(in DOMString scope, in nsIPrincipal principal, in nsIUnsubscribeResultCallback callback); + + void getSubscription(in DOMString scope, in nsIPrincipal principal, in nsIPushEndpointCallback callback); +}; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index a1eca72b5ba..aef9a009668 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1121,12 +1121,15 @@ ContentParent::RecvGetBlocklistState(const uint32_t& aPluginId, nsRefPtr pluginHost = nsPluginHost::GetInst(); if (!pluginHost) { + NS_WARNING("Plugin host not found"); return false; } nsPluginTag* tag = pluginHost->PluginWithId(aPluginId); if (!tag) { - return false; + // Default state is blocked anyway + NS_WARNING("Plugin tag not found. This should never happen, but to avoid a crash we're forcibly blocking it"); + return true; } return NS_SUCCEEDED(tag->GetBlocklistState(aState)); diff --git a/dom/ipc/ProcessHangMonitor.cpp b/dom/ipc/ProcessHangMonitor.cpp index c9a445c125e..a49337c7030 100644 --- a/dom/ipc/ProcessHangMonitor.cpp +++ b/dom/ipc/ProcessHangMonitor.cpp @@ -750,7 +750,7 @@ HangMonitoredProcess::GetPluginName(nsACString& aPluginName) return NS_ERROR_UNEXPECTED; } - aPluginName = tag->mName; + aPluginName = tag->Name(); return NS_OK; } diff --git a/dom/ipc/jar.mn b/dom/ipc/jar.mn index 57395c39c22..e009460ae90 100644 --- a/dom/ipc/jar.mn +++ b/dom/ipc/jar.mn @@ -11,5 +11,4 @@ toolkit.jar: content/global/BrowserElementPanning.js (../browser-element/BrowserElementPanning.js) * content/global/BrowserElementPanningAPZDisabled.js (../browser-element/BrowserElementPanningAPZDisabled.js) content/global/manifestMessages.js (manifestMessages.js) - content/global/PushServiceChildPreload.js (../push/PushServiceChildPreload.js) content/global/preload.js (preload.js) diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 2ca215ca06f..08929dd1497 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -217,6 +217,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, mDecodeToSeekTarget(false), mCurrentTimeBeforeSeek(0), mCorruptFrames(30), + mDecodingFirstFrame(true), mDisabledHardwareAcceleration(false), mDecodingFrozenAtStateDecoding(false), mSentLoadedMetadataEvent(false), @@ -441,7 +442,7 @@ MediaDecoderStateMachine::NeedToDecodeVideo() HaveEnoughDecodedVideo()); return IsVideoDecoding() && ((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) || - (mState == DECODER_STATE_DECODING_FIRSTFRAME && + (IsDecodingFirstFrame() && IsVideoDecoding() && VideoQueue().GetSize() == 0) || (!mMinimizePreroll && !HaveEnoughDecodedVideo())); } @@ -451,7 +452,7 @@ MediaDecoderStateMachine::NeedToSkipToNextKeyframe() { MOZ_ASSERT(OnTaskQueue()); AssertCurrentThreadInMonitor(); - if (mState == DECODER_STATE_DECODING_FIRSTFRAME) { + if (IsDecodingFirstFrame()) { return false; } MOZ_ASSERT(mState == DECODER_STATE_DECODING || @@ -508,7 +509,7 @@ MediaDecoderStateMachine::NeedToDecodeAudio() return IsAudioDecoding() && ((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) || - (mState == DECODER_STATE_DECODING_FIRSTFRAME && + (IsDecodingFirstFrame() && IsAudioDecoding() && AudioQueue().GetSize() == 0) || (!mMinimizePreroll && !HaveEnoughDecodedAudio(mAmpleAudioThresholdUsecs * mPlaybackRate) && @@ -560,12 +561,6 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample) (audio ? audio->mDiscontinuity : 0)); switch (mState) { - case DECODER_STATE_DECODING_FIRSTFRAME: { - Push(audio); - MaybeFinishDecodeFirstFrame(); - return; - } - case DECODER_STATE_BUFFERING: { // If we're buffering, this may be the sample we need to stop buffering. // Save it and schedule the state machine. @@ -576,6 +571,9 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample) case DECODER_STATE_DECODING: { Push(audio); + if (MaybeFinishDecodeFirstFrame()) { + return; + } if (mIsAudioPrerolling && DonePrerollingAudio()) { StopPrerollingAudio(); } @@ -781,13 +779,11 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType, StopPrerollingVideo(); } switch (mState) { - case DECODER_STATE_DECODING_FIRSTFRAME: { - MaybeFinishDecodeFirstFrame(); - return; - } - case DECODER_STATE_BUFFERING: case DECODER_STATE_DECODING: { + if (MaybeFinishDecodeFirstFrame()) { + return; + } CheckIfDecodeComplete(); mDecoder->GetReentrantMonitor().NotifyAll(); // Tell AudioSink to wake up for audio queue is finished. @@ -821,18 +817,26 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType, } } -void +bool MediaDecoderStateMachine::MaybeFinishDecodeFirstFrame() { MOZ_ASSERT(OnTaskQueue()); AssertCurrentThreadInMonitor(); - if ((IsAudioDecoding() && AudioQueue().GetSize() == 0) || + if (!IsDecodingFirstFrame() || + (IsAudioDecoding() && AudioQueue().GetSize() == 0) || (IsVideoDecoding() && VideoQueue().GetSize() == 0)) { - return; + return false; } - if (NS_FAILED(FinishDecodeFirstFrame())) { - DecodeError(); + FinishDecodeFirstFrame(); + if (!mQueuedSeek.Exists()) { + return false; } + + // We can now complete the pending seek. + mPendingSeek.Steal(mQueuedSeek); + SetState(DECODER_STATE_SEEKING); + ScheduleStateMachine(); + return true; } void @@ -852,12 +856,6 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample) (video ? video->mDiscontinuity : 0)); switch (mState) { - case DECODER_STATE_DECODING_FIRSTFRAME: { - Push(video); - MaybeFinishDecodeFirstFrame(); - return; - } - case DECODER_STATE_BUFFERING: { // If we're buffering, this may be the sample we need to stop buffering. // Save it and schedule the state machine. @@ -868,6 +866,9 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample) case DECODER_STATE_DECODING: { Push(video); + if (MaybeFinishDecodeFirstFrame()) { + return; + } if (mIsVideoPrerolling && DonePrerollingVideo()) { StopPrerollingVideo(); } @@ -892,7 +893,8 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample) return; } TimeDuration decodeTime = TimeStamp::Now() - mVideoDecodeStartTime; - if (THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs && + if (!IsDecodingFirstFrame() && + THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs && !HasLowUndecodedData()) { mLowAudioThresholdUsecs = @@ -1144,7 +1146,6 @@ static const char* const gMachineStateStr[] = { "DECODING_METADATA", "WAIT_FOR_RESOURCES", "WAIT_FOR_CDM", - "DECODING_FIRSTFRAME", "DORMANT", "DECODING", "SEEKING", @@ -1274,6 +1275,7 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant) mDecodingFrozenAtStateDecoding = true; ScheduleStateMachine(); mCurrentPosition = 0; + mDecodingFirstFrame = true; SetState(DECODER_STATE_DECODING_NONE); mDecoder->GetReentrantMonitor().NotifyAll(); } @@ -1319,11 +1321,32 @@ void MediaDecoderStateMachine::StartDecoding() { MOZ_ASSERT(OnTaskQueue()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - if (mState == DECODER_STATE_DECODING) { + if (mState == DECODER_STATE_DECODING && !mDecodingFirstFrame) { return; } SetState(DECODER_STATE_DECODING); + if (mDecodingFirstFrame && + (IsRealTime() || mSentFirstFrameLoadedEvent)) { + if (IsRealTime()) { + FinishDecodeFirstFrame(); + } else { + // We're resuming from dormant state, so we don't need to request + // the first samples in order to determine the media start time, + // we have the start time from last time we loaded. + // FinishDecodeFirstFrame will be launched upon completion of the seek when + // we have data ready to play. + MOZ_ASSERT(mQueuedSeek.Exists() && mSentFirstFrameLoadedEvent, + "Return from dormant must have queued seek"); + } + if (mQueuedSeek.Exists()) { + mPendingSeek.Steal(mQueuedSeek); + SetState(DECODER_STATE_SEEKING); + ScheduleStateMachine(); + return; + } + } + mDecodeStartTime = TimeStamp::Now(); CheckIfDecodeComplete(); @@ -1353,8 +1376,7 @@ void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged() ScheduleStateMachine(); } else if (mState == DECODER_STATE_WAIT_FOR_CDM && !mReader->IsWaitingOnCDMResource()) { - SetState(DECODER_STATE_DECODING_FIRSTFRAME); - EnqueueDecodeFirstFrameTask(); + StartDecoding(); } } @@ -1454,7 +1476,8 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget) NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA, "We should have got duration already"); - if (mState < DECODER_STATE_DECODING) { + if (mState < DECODER_STATE_DECODING || + (IsDecodingFirstFrame() && !mReader->ForceZeroStartTime())) { DECODER_LOG("Seek() Not Enough Data to continue at this stage, queuing seek"); mQueuedSeek.RejectIfExists(__func__); mQueuedSeek.mTarget = aTarget; @@ -1484,19 +1507,6 @@ void MediaDecoderStateMachine::StopAudioThread() mAudioSinkPromise.DisconnectIfExists(); } -nsresult -MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask() -{ - MOZ_ASSERT(OnTaskQueue()); - AssertCurrentThreadInMonitor(); - MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME); - - nsCOMPtr task( - NS_NewRunnableMethod(this, &MediaDecoderStateMachine::CallDecodeFirstFrame)); - OwnerThread()->Dispatch(task.forget()); - return NS_OK; -} - void MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded() { @@ -1504,7 +1514,6 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded() AssertCurrentThreadInMonitor(); if (mState != DECODER_STATE_DECODING && - mState != DECODER_STATE_DECODING_FIRSTFRAME && mState != DECODER_STATE_BUFFERING && mState != DECODER_STATE_SEEKING) { return; @@ -1653,7 +1662,6 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued() IsAudioDecoding(), AudioRequestStatus()); if (mState != DECODER_STATE_DECODING && - mState != DECODER_STATE_DECODING_FIRSTFRAME && mState != DECODER_STATE_BUFFERING && mState != DECODER_STATE_SEEKING) { return NS_OK; @@ -1725,7 +1733,6 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued() IsVideoDecoding(), VideoRequestStatus()); if (mState != DECODER_STATE_DECODING && - mState != DECODER_STATE_DECODING_FIRSTFRAME && mState != DECODER_STATE_BUFFERING && mState != DECODER_STATE_SEEKING) { return NS_OK; @@ -1862,7 +1869,7 @@ bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs) { MOZ_ASSERT(OnTaskQueue()); AssertCurrentThreadInMonitor(); - NS_ASSERTION(mState > DECODER_STATE_DECODING_FIRSTFRAME, + NS_ASSERTION(mState >= DECODER_STATE_DECODING && !IsDecodingFirstFrame(), "Must have loaded first frame for mBuffered to be valid"); // If we don't have a duration, mBuffered is probably not going to have @@ -1993,8 +2000,8 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata) return; } - SetState(DECODER_STATE_DECODING_FIRSTFRAME); - EnqueueDecodeFirstFrameTask(); + StartDecoding(); + ScheduleStateMachine(); } @@ -2045,60 +2052,19 @@ MediaDecoderStateMachine::EnqueueFirstFrameLoadedEvent() mSentFirstFrameLoadedEvent = true; } +bool +MediaDecoderStateMachine::IsDecodingFirstFrame() +{ + return mState == DECODER_STATE_DECODING && mDecodingFirstFrame; +} + void -MediaDecoderStateMachine::CallDecodeFirstFrame() -{ - MOZ_ASSERT(OnTaskQueue()); - ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - if (mState != DECODER_STATE_DECODING_FIRSTFRAME) { - return; - } - if (NS_FAILED(DecodeFirstFrame())) { - DECODER_WARN("Decode failed to start, shutting down decoder"); - DecodeError(); - } -} - -nsresult -MediaDecoderStateMachine::DecodeFirstFrame() -{ - MOZ_ASSERT(OnTaskQueue()); - AssertCurrentThreadInMonitor(); - MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME); - DECODER_LOG("DecodeFirstFrame started"); - - if (IsRealTime()) { - nsresult res = FinishDecodeFirstFrame(); - NS_ENSURE_SUCCESS(res, res); - } else if (mSentFirstFrameLoadedEvent) { - // We're resuming from dormant state, so we don't need to request - // the first samples in order to determine the media start time, - // we have the start time from last time we loaded. - nsresult res = FinishDecodeFirstFrame(); - NS_ENSURE_SUCCESS(res, res); - } else { - if (HasAudio()) { - RequestAudioData(); - } - if (HasVideo()) { - RequestVideoData(); - } - } - - return NS_OK; -} - -nsresult MediaDecoderStateMachine::FinishDecodeFirstFrame() { MOZ_ASSERT(OnTaskQueue()); AssertCurrentThreadInMonitor(); DECODER_LOG("FinishDecodeFirstFrame"); - if (IsShutdown()) { - return NS_ERROR_FAILURE; - } - if (!IsRealTime() && !mSentFirstFrameLoadedEvent) { RenderVideoFrames(1); } @@ -2112,7 +2078,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame() "transportSeekable=%d, mediaSeekable=%d", Duration().ToMicroseconds(), mDecoder->IsTransportSeekable(), mDecoder->IsMediaSeekable()); - if (HasAudio() && !HasVideo()) { + if (HasAudio() && !HasVideo() && !mSentFirstFrameLoadedEvent) { // We're playing audio only. We don't need to worry about slow video // decodes causing audio underruns, so don't buffer so much audio in // order to reduce memory usage. @@ -2133,16 +2099,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame() } EnqueueFirstFrameLoadedEvent(); - if (mQueuedSeek.Exists()) { - mPendingSeek.Steal(mQueuedSeek); - SetState(DECODER_STATE_SEEKING); - ScheduleStateMachine(); - } else if (mState == DECODER_STATE_DECODING_FIRSTFRAME) { - // StartDecoding() will also check if decode is completed. - StartDecoding(); - } - - return NS_OK; + mDecodingFirstFrame = false; } void @@ -2175,6 +2132,12 @@ MediaDecoderStateMachine::SeekCompleted() } mPlayDuration = newCurrentTime; + if (mDecodingFirstFrame) { + // We were resuming from dormant, or initiated a seek early. + // We can fire loadeddata now. + FinishDecodeFirstFrame(); + } + // Change state to DECODING or COMPLETED now. SeekingStopped will // call MediaDecoderStateMachine::Seek to reset our state to SEEKING // if we need to seek again. @@ -2338,12 +2301,12 @@ nsresult MediaDecoderStateMachine::RunStateMachine() return NS_OK; } - case DECODER_STATE_DECODING_FIRSTFRAME: { - // DECODER_STATE_DECODING_FIRSTFRAME will be started by OnMetadataRead. - return NS_OK; - } - case DECODER_STATE_DECODING: { + if (IsDecodingFirstFrame()) { + // We haven't completed decoding our first frames, we can't start + // playback yet. + return NS_OK; + } if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying()) { // We're playing, but the element/decoder is in paused state. Stop @@ -2890,7 +2853,7 @@ void MediaDecoderStateMachine::UpdateNextFrameStatus() MediaDecoderOwner::NextFrameStatus status; const char* statusString; - if (mState <= DECODER_STATE_DECODING_FIRSTFRAME) { + if (mState <= DECODER_STATE_WAIT_FOR_CDM || IsDecodingFirstFrame()) { status = MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE; statusString = "NEXT_FRAME_UNAVAILABLE"; } else if (IsBuffering()) { diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index ea485d4e9d0..ac5bc525ad2 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -138,7 +138,6 @@ public: DECODER_STATE_DECODING_METADATA, DECODER_STATE_WAIT_FOR_RESOURCES, DECODER_STATE_WAIT_FOR_CDM, - DECODER_STATE_DECODING_FIRSTFRAME, DECODER_STATE_DORMANT, DECODER_STATE_DECODING, DECODER_STATE_SEEKING, @@ -407,8 +406,6 @@ protected: MediaQueue& AudioQueue() { return mAudioQueue; } MediaQueue& VideoQueue() { return mVideoQueue; } - nsresult FinishDecodeFirstFrame(); - // True if our buffers of decoded audio are not full, and we should // decode more. bool NeedToDecodeAudio(); @@ -555,11 +552,6 @@ protected: void EnqueueFirstFrameLoadedEvent(); - // Dispatches a task to the state machine thread to begin decoding content. - // This is threadsafe and can be called on any thread. - // The decoder monitor must be held. - nsresult EnqueueDecodeFirstFrameTask(); - // Clears any previous seeking state and initiates a new see on the decoder. // The decoder monitor must be held. void InitiateSeek(); @@ -617,16 +609,14 @@ protected: void OnMetadataRead(MetadataHolder* aMetadata); void OnMetadataNotRead(ReadMetadataFailureReason aReason); - // Initiate first content decoding. Called on the state machine thread. - // The decoder monitor must be held with exactly one lock count. - nsresult DecodeFirstFrame(); - - // Wraps the call to DecodeFirstFrame(), signals a DecodeError() on failure. - void CallDecodeFirstFrame(); - - // Checks whether we're finished decoding first audio and/or video packets, - // and switches to DECODING state if so. - void MaybeFinishDecodeFirstFrame(); + // Checks whether we're finished decoding first audio and/or video packets. + // If so will trigger firing loadeddata event. + // If there are any queued seek, will change state to DECODER_STATE_SEEKING + // and return true. + bool MaybeFinishDecodeFirstFrame(); + // Return true if we are currently decoding the first frames. + bool IsDecodingFirstFrame(); + void FinishDecodeFirstFrame(); // Seeks to mSeekTarget. Called on the decode thread. The decoder monitor // must be held with exactly one lock count. @@ -1262,6 +1252,10 @@ private: mozilla::RollingMean mCorruptFrames; + // True if we need to call FinishDecodeFirstFrame() upon frame decoding + // successeeding. + bool mDecodingFirstFrame; + bool mDisabledHardwareAcceleration; // mDecodingFrozenAtStateDecoding: turn on/off at diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index 81f8c9b5463..f6220cee495 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -715,6 +715,7 @@ MediaFormatReader::NotifyDrainComplete(TrackType aTrack) { MOZ_ASSERT(OnTaskQueue()); auto& decoder = GetDecoderData(aTrack); + LOG("%s", TrackTypeToStr(aTrack)); if (!decoder.mOutputRequested) { LOG("MediaFormatReader called DrainComplete() before flushing, ignoring."); return; @@ -983,6 +984,11 @@ MediaFormatReader::DrainDecoder(TrackType aTrack) return; } decoder.mOutputRequested = true; + if (decoder.mNumSamplesInput == decoder.mNumSamplesOutput) { + // No frames to drain. + NotifyDrainComplete(aTrack); + return; + } decoder.mDecoder->Drain(); decoder.mDraining = true; LOG("Requesting %s decoder to drain", TrackTypeToStr(aTrack)); diff --git a/dom/media/eme/DetailedPromise.cpp b/dom/media/eme/DetailedPromise.cpp index 863a9634a30..3d72995a021 100644 --- a/dom/media/eme/DetailedPromise.cpp +++ b/dom/media/eme/DetailedPromise.cpp @@ -6,12 +6,15 @@ #include "DetailedPromise.h" #include "mozilla/dom/DOMException.h" +#include "nsPrintfCString.h" namespace mozilla { namespace dom { -DetailedPromise::DetailedPromise(nsIGlobalObject* aGlobal) +DetailedPromise::DetailedPromise(nsIGlobalObject* aGlobal, + const nsACString& aName) : Promise(aGlobal) + , mName(aName) , mResponded(false) { } @@ -21,25 +24,16 @@ DetailedPromise::~DetailedPromise() MOZ_ASSERT(mResponded == IsPending()); } -static void -LogToConsole(const nsAString& aMsg) -{ - nsCOMPtr console( - do_GetService("@mozilla.org/consoleservice;1")); - if (!console) { - NS_WARNING("Failed to log message to console."); - return; - } - nsAutoString msg(aMsg); - console->LogStringMessage(msg.get()); -} - void DetailedPromise::MaybeReject(nsresult aArg, const nsACString& aReason) { + nsPrintfCString msg("%s promise rejected 0x%x '%s'", mName.get(), aArg, + PromiseFlatCString(aReason).get()); + EME_LOG(msg.get()); + mResponded = true; - LogToConsole(NS_ConvertUTF8toUTF16(aReason)); + LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg)); nsRefPtr exception = DOMException::Create(aArg, aReason); @@ -53,9 +47,11 @@ DetailedPromise::MaybeReject(ErrorResult&, const nsACString& aReason) } /* static */ already_AddRefed -DetailedPromise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv) +DetailedPromise::Create(nsIGlobalObject* aGlobal, + ErrorResult& aRv, + const nsACString& aName) { - nsRefPtr promise = new DetailedPromise(aGlobal); + nsRefPtr promise = new DetailedPromise(aGlobal, aName); promise->CreateWrapper(aRv); return aRv.Failed() ? nullptr : promise.forget(); } diff --git a/dom/media/eme/DetailedPromise.h b/dom/media/eme/DetailedPromise.h index 922e95f58e7..0b919fa53c6 100644 --- a/dom/media/eme/DetailedPromise.h +++ b/dom/media/eme/DetailedPromise.h @@ -8,6 +8,7 @@ #define __DetailedPromise_h__ #include "mozilla/dom/Promise.h" +#include "EMEUtils.h" namespace mozilla { namespace dom { @@ -21,11 +22,12 @@ class DetailedPromise : public Promise { public: static already_AddRefed - Create(nsIGlobalObject* aGlobal, ErrorResult& aRv); + Create(nsIGlobalObject* aGlobal, ErrorResult& aRv, const nsACString& aName); template void MaybeResolve(const T& aArg) { + EME_LOG("%s promise resolved", mName.get()); mResponded = true; Promise::MaybeResolve(aArg); } @@ -37,9 +39,10 @@ public: void MaybeReject(ErrorResult&, const nsACString& aReason); private: - explicit DetailedPromise(nsIGlobalObject* aGlobal); + explicit DetailedPromise(nsIGlobalObject* aGlobal, const nsACString& aName); virtual ~DetailedPromise(); + nsCString mName; bool mResponded; }; diff --git a/dom/media/eme/EMEUtils.cpp b/dom/media/eme/EMEUtils.cpp index 6137862cdd7..443adbea8ba 100644 --- a/dom/media/eme/EMEUtils.cpp +++ b/dom/media/eme/EMEUtils.cpp @@ -5,6 +5,8 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/EMEUtils.h" +#include "nsServiceManagerUtils.h" +#include "nsIConsoleService.h" namespace mozilla { @@ -109,4 +111,17 @@ ParseKeySystem(const nsAString& aInputKeySystem, return false; } +void +LogToBrowserConsole(const nsAString& aMsg) +{ + nsCOMPtr console( + do_GetService("@mozilla.org/consoleservice;1")); + if (!console) { + NS_WARNING("Failed to log message to console."); + return; + } + nsAutoString msg(aMsg); + console->LogStringMessage(msg.get()); +} + } // namespace mozilla diff --git a/dom/media/eme/EMEUtils.h b/dom/media/eme/EMEUtils.h index 44165b51215..fef99cac7fe 100644 --- a/dom/media/eme/EMEUtils.h +++ b/dom/media/eme/EMEUtils.h @@ -51,6 +51,9 @@ bool ParseKeySystem(const nsAString& aKeySystem, nsAString& aOutKeySystem, int32_t& aOutMinCDMVersion); +void +LogToBrowserConsole(const nsAString& aMsg); + } // namespace mozilla #endif // EME_LOG_H_ diff --git a/dom/media/eme/MediaKeySession.cpp b/dom/media/eme/MediaKeySession.cpp index 7b64ba18cb0..fb979757f49 100644 --- a/dom/media/eme/MediaKeySession.cpp +++ b/dom/media/eme/MediaKeySession.cpp @@ -60,7 +60,7 @@ MediaKeySession::MediaKeySession(JSContext* aCx, if (aRv.Failed()) { return; } - mClosed = MakePromise(aRv); + mClosed = MakePromise(aRv, NS_LITERAL_CSTRING("MediaKeys.createSession")); } void MediaKeySession::SetSessionId(const nsAString& aSessionId) @@ -169,7 +169,8 @@ MediaKeySession::GenerateRequest(const nsAString& aInitDataType, const ArrayBufferViewOrArrayBuffer& aInitData, ErrorResult& aRv) { - nsRefPtr promise(MakePromise(aRv)); + nsRefPtr promise(MakePromise(aRv, + NS_LITERAL_CSTRING("MediaKeySession.generateRequest"))); if (aRv.Failed()) { return nullptr; } @@ -226,7 +227,8 @@ MediaKeySession::GenerateRequest(const nsAString& aInitDataType, already_AddRefed MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv) { - nsRefPtr promise(MakePromise(aRv)); + nsRefPtr promise(MakePromise(aRv, + NS_LITERAL_CSTRING("MediaKeySession.load"))); if (aRv.Failed()) { return nullptr; } @@ -269,7 +271,8 @@ MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv) already_AddRefed MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResult& aRv) { - nsRefPtr promise(MakePromise(aRv)); + nsRefPtr promise(MakePromise(aRv, + NS_LITERAL_CSTRING("MediaKeySession.update"))); if (aRv.Failed()) { return nullptr; } @@ -320,7 +323,8 @@ MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResu already_AddRefed MediaKeySession::Close(ErrorResult& aRv) { - nsRefPtr promise(MakePromise(aRv)); + nsRefPtr promise(MakePromise(aRv, + NS_LITERAL_CSTRING("MediaKeySession.close"))); if (aRv.Failed()) { return nullptr; } @@ -362,7 +366,8 @@ MediaKeySession::IsClosed() const already_AddRefed MediaKeySession::Remove(ErrorResult& aRv) { - nsRefPtr promise(MakePromise(aRv)); + nsRefPtr promise(MakePromise(aRv, + NS_LITERAL_CSTRING("MediaKeySession.remove"))); if (aRv.Failed()) { return nullptr; } @@ -447,7 +452,7 @@ MediaKeySession::Token() const } already_AddRefed -MediaKeySession::MakePromise(ErrorResult& aRv) +MediaKeySession::MakePromise(ErrorResult& aRv, const nsACString& aName) { nsCOMPtr global = do_QueryInterface(GetParentObject()); if (!global) { @@ -455,7 +460,7 @@ MediaKeySession::MakePromise(ErrorResult& aRv) aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } - return DetailedPromise::Create(global, aRv); + return DetailedPromise::Create(global, aRv, aName); } } // namespace dom diff --git a/dom/media/eme/MediaKeySession.h b/dom/media/eme/MediaKeySession.h index d48597ea88e..2d3fd23c7f3 100644 --- a/dom/media/eme/MediaKeySession.h +++ b/dom/media/eme/MediaKeySession.h @@ -98,7 +98,8 @@ private: ~MediaKeySession(); void UpdateKeyStatusMap(); - already_AddRefed MakePromise(ErrorResult& aRv); + already_AddRefed MakePromise(ErrorResult& aRv, + const nsACString& aName); nsRefPtr mClosed; diff --git a/dom/media/eme/MediaKeySystemAccessManager.cpp b/dom/media/eme/MediaKeySystemAccessManager.cpp index 5212f92d959..3b1a8d9e438 100644 --- a/dom/media/eme/MediaKeySystemAccessManager.cpp +++ b/dom/media/eme/MediaKeySystemAccessManager.cpp @@ -13,6 +13,7 @@ #ifdef XP_WIN #include "mozilla/WindowsVersion.h" #endif +#include "nsPrintfCString.h" namespace mozilla { namespace dom { @@ -106,7 +107,17 @@ MediaKeySystemAccessManager::Request(DetailedPromise* aPromise, } nsAutoCString message; - MediaKeySystemStatus status = MediaKeySystemAccess::GetKeySystemStatus(keySystem, minCdmVersion, message); + MediaKeySystemStatus status = + MediaKeySystemAccess::GetKeySystemStatus(keySystem, minCdmVersion, message); + + nsPrintfCString msg("MediaKeySystemAccess::GetKeySystemStatus(%s, minVer=%d) " + "result=%s msg='%s'", + NS_ConvertUTF16toUTF8(keySystem).get(), + minCdmVersion, + MediaKeySystemStatusValues::strings[(size_t)status].value, + message.get()); + LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg)); + if ((status == MediaKeySystemStatus::Cdm_not_installed || status == MediaKeySystemStatus::Cdm_insufficient_version) && keySystem.EqualsLiteral("com.adobe.primetime")) { @@ -139,8 +150,7 @@ MediaKeySystemAccessManager::Request(DetailedPromise* aPromise, // chrome, so we can show some UI to explain how the user can rectify // the situation. MediaKeySystemAccess::NotifyObservers(mWindow, keySystem, status); - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("The key system has been disabled by the user")); + aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, message); return; } aPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, diff --git a/dom/media/eme/MediaKeys.cpp b/dom/media/eme/MediaKeys.cpp index 40fcb6791a4..83f3a843098 100644 --- a/dom/media/eme/MediaKeys.cpp +++ b/dom/media/eme/MediaKeys.cpp @@ -147,8 +147,8 @@ MediaKeys::GetKeySystem(nsString& retval) const already_AddRefed MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, ErrorResult& aRv) { - nsRefPtr - promise(MakePromise(aRv)); + nsRefPtr promise(MakePromise(aRv, + NS_LITERAL_CSTRING("MediaKeys.setServerCertificate"))); if (aRv.Failed()) { return nullptr; } @@ -172,7 +172,7 @@ MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, Error } already_AddRefed -MediaKeys::MakePromise(ErrorResult& aRv) +MediaKeys::MakePromise(ErrorResult& aRv, const nsACString& aName) { nsCOMPtr global = do_QueryInterface(GetParentObject()); if (!global) { @@ -180,7 +180,7 @@ MediaKeys::MakePromise(ErrorResult& aRv) aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } - return DetailedPromise::Create(global, aRv); + return DetailedPromise::Create(global, aRv, aName); } PromiseId @@ -295,8 +295,8 @@ MediaKeys::ResolvePromise(PromiseId aId) already_AddRefed MediaKeys::Init(ErrorResult& aRv) { - nsRefPtr - promise(MakePromise(aRv)); + nsRefPtr promise(MakePromise(aRv, + NS_LITERAL_CSTRING("MediaKeys::Init()"))); if (aRv.Failed()) { return nullptr; } diff --git a/dom/media/eme/MediaKeys.h b/dom/media/eme/MediaKeys.h index 74f937331b9..aa74ee4b168 100644 --- a/dom/media/eme/MediaKeys.h +++ b/dom/media/eme/MediaKeys.h @@ -99,7 +99,8 @@ public: CDMProxy* GetCDMProxy() { return mProxy; } // Makes a new promise, or nullptr on failure. - already_AddRefed MakePromise(ErrorResult& aRv); + already_AddRefed MakePromise(ErrorResult& aRv, + const nsACString& aName); // Stores promise in mPromises, returning an ID that can be used to retrieve // it later. The ID is passed to the CDM, so that it can signal specific // promises to be resolved. diff --git a/dom/media/gmp/GMPAudioDecoderParent.cpp b/dom/media/gmp/GMPAudioDecoderParent.cpp index 2b801b45433..72facefc3fb 100644 --- a/dom/media/gmp/GMPAudioDecoderParent.cpp +++ b/dom/media/gmp/GMPAudioDecoderParent.cpp @@ -28,6 +28,8 @@ GMPAudioDecoderParent::GMPAudioDecoderParent(GMPContentParent* aPlugin) : mIsOpen(false) , mShuttingDown(false) , mActorDestroyed(false) + , mIsAwaitingResetComplete(false) + , mIsAwaitingDrainComplete(false) , mPlugin(aPlugin) , mCallback(nullptr) { @@ -109,6 +111,8 @@ GMPAudioDecoderParent::Reset() return NS_ERROR_FAILURE; } + mIsAwaitingResetComplete = true; + // Async IPC, we don't have access to a return value. return NS_OK; } @@ -127,6 +131,8 @@ GMPAudioDecoderParent::Drain() return NS_ERROR_FAILURE; } + mIsAwaitingDrainComplete = true; + // Async IPC, we don't have access to a return value. return NS_OK; } @@ -138,6 +144,11 @@ GMPAudioDecoderParent::Close() LOGD(("%s: %p", __FUNCTION__, this)); MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread()); + // Ensure if we've received a Close while waiting for a ResetComplete + // or DrainComplete notification, we'll unblock the caller before processing + // the close. This seems unlikely to happen, but better to be careful. + UnblockResetAndDrain(); + // Consumer is done with us; we can shut down. No more callbacks should // be made to mCallback. Note: do this before Shutdown()! mCallback = nullptr; @@ -163,6 +174,11 @@ GMPAudioDecoderParent::Shutdown() } mShuttingDown = true; + // Ensure if we've received a shutdown while waiting for a ResetComplete + // or DrainComplete notification, we'll unblock the caller before processing + // the shutdown. + UnblockResetAndDrain(); + // Notify client we're gone! Won't occur after Close() if (mCallback) { mCallback->Terminated(); @@ -183,6 +199,12 @@ GMPAudioDecoderParent::ActorDestroy(ActorDestroyReason aWhy) { mIsOpen = false; mActorDestroyed = true; + + // Ensure if we've received a destroy while waiting for a ResetComplete + // or DrainComplete notification, we'll unblock the caller before processing + // the error. + UnblockResetAndDrain(); + if (mCallback) { // May call Close() (and Shutdown()) immediately or with a delay mCallback->Terminated(); @@ -230,6 +252,11 @@ GMPAudioDecoderParent::RecvDrainComplete() return false; } + if (!mIsAwaitingDrainComplete) { + return true; + } + mIsAwaitingDrainComplete = false; + // Ignore any return code. It is OK for this to fail without killing the process. mCallback->DrainComplete(); @@ -243,6 +270,11 @@ GMPAudioDecoderParent::RecvResetComplete() return false; } + if (!mIsAwaitingResetComplete) { + return true; + } + mIsAwaitingResetComplete = false; + // Ignore any return code. It is OK for this to fail without killing the process. mCallback->ResetComplete(); @@ -256,6 +288,11 @@ GMPAudioDecoderParent::RecvError(const GMPErr& aError) return false; } + // Ensure if we've received an error while waiting for a ResetComplete + // or DrainComplete notification, we'll unblock the caller before processing + // the error. + UnblockResetAndDrain(); + // Ignore any return code. It is OK for this to fail without killing the process. mCallback->Error(aError); @@ -281,5 +318,23 @@ GMPAudioDecoderParent::Recv__delete__() return true; } +void +GMPAudioDecoderParent::UnblockResetAndDrain() +{ + if (!mCallback) { + MOZ_ASSERT(!mIsAwaitingResetComplete); + MOZ_ASSERT(!mIsAwaitingDrainComplete); + return; + } + if (mIsAwaitingResetComplete) { + mIsAwaitingResetComplete = false; + mCallback->ResetComplete(); + } + if (mIsAwaitingDrainComplete) { + mIsAwaitingDrainComplete = false; + mCallback->DrainComplete(); + } +} + } // namespace gmp } // namespace mozilla diff --git a/dom/media/gmp/GMPAudioDecoderParent.h b/dom/media/gmp/GMPAudioDecoderParent.h index 8379f6f89fe..cb19021f5d7 100644 --- a/dom/media/gmp/GMPAudioDecoderParent.h +++ b/dom/media/gmp/GMPAudioDecoderParent.h @@ -53,9 +53,13 @@ private: virtual bool RecvShutdown() override; virtual bool Recv__delete__() override; + void UnblockResetAndDrain(); + bool mIsOpen; bool mShuttingDown; bool mActorDestroyed; + bool mIsAwaitingResetComplete; + bool mIsAwaitingDrainComplete; nsRefPtr mPlugin; GMPAudioDecoderCallbackProxy* mCallback; }; diff --git a/dom/media/gmp/GMPVideoDecoderParent.cpp b/dom/media/gmp/GMPVideoDecoderParent.cpp index 8491a67d15d..68e633f8701 100644 --- a/dom/media/gmp/GMPVideoDecoderParent.cpp +++ b/dom/media/gmp/GMPVideoDecoderParent.cpp @@ -43,6 +43,8 @@ GMPVideoDecoderParent::GMPVideoDecoderParent(GMPContentParent* aPlugin) , mIsOpen(false) , mShuttingDown(false) , mActorDestroyed(false) + , mIsAwaitingResetComplete(false) + , mIsAwaitingDrainComplete(false) , mPlugin(aPlugin) , mCallback(nullptr) , mVideoHost(this) @@ -67,6 +69,12 @@ GMPVideoDecoderParent::Close() { LOGD(("%s: %p", __FUNCTION__, this)); MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread()); + + // Ensure if we've received a Close while waiting for a ResetComplete + // or DrainComplete notification, we'll unblock the caller before processing + // the close. This seems unlikely to happen, but better to be careful. + UnblockResetAndDrain(); + // Consumer is done with us; we can shut down. No more callbacks should // be made to mCallback. Note: do this before Shutdown()! mCallback = nullptr; @@ -161,6 +169,8 @@ GMPVideoDecoderParent::Reset() return NS_ERROR_FAILURE; } + mIsAwaitingResetComplete = true; + // Async IPC, we don't have access to a return value. return NS_OK; } @@ -179,6 +189,8 @@ GMPVideoDecoderParent::Drain() return NS_ERROR_FAILURE; } + mIsAwaitingDrainComplete = true; + // Async IPC, we don't have access to a return value. return NS_OK; } @@ -207,6 +219,11 @@ GMPVideoDecoderParent::Shutdown() } mShuttingDown = true; + // Ensure if we've received a shutdown while waiting for a ResetComplete + // or DrainComplete notification, we'll unblock the caller before processing + // the shutdown. + UnblockResetAndDrain(); + // Notify client we're gone! Won't occur after Close() if (mCallback) { mCallback->Terminated(); @@ -229,6 +246,11 @@ GMPVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy) mActorDestroyed = true; mVideoHost.DoneWithAPI(); + // Ensure if we've received a destroy while waiting for a ResetComplete + // or DrainComplete notification, we'll unblock the caller before processing + // the error. + UnblockResetAndDrain(); + if (mCallback) { // May call Close() (and Shutdown()) immediately or with a delay mCallback->Terminated(); @@ -307,6 +329,11 @@ GMPVideoDecoderParent::RecvDrainComplete() return false; } + if (!mIsAwaitingDrainComplete) { + return true; + } + mIsAwaitingDrainComplete = false; + // Ignore any return code. It is OK for this to fail without killing the process. mCallback->DrainComplete(); @@ -320,6 +347,11 @@ GMPVideoDecoderParent::RecvResetComplete() return false; } + if (!mIsAwaitingResetComplete) { + return true; + } + mIsAwaitingResetComplete = false; + // Ignore any return code. It is OK for this to fail without killing the process. mCallback->ResetComplete(); @@ -333,6 +365,11 @@ GMPVideoDecoderParent::RecvError(const GMPErr& aError) return false; } + // Ensure if we've received an error while waiting for a ResetComplete + // or DrainComplete notification, we'll unblock the caller before processing + // the error. + UnblockResetAndDrain(); + // Ignore any return code. It is OK for this to fail without killing the process. mCallback->Error(aError); @@ -387,5 +424,23 @@ GMPVideoDecoderParent::Recv__delete__() return true; } +void +GMPVideoDecoderParent::UnblockResetAndDrain() +{ + if (!mCallback) { + MOZ_ASSERT(!mIsAwaitingResetComplete); + MOZ_ASSERT(!mIsAwaitingDrainComplete); + return; + } + if (mIsAwaitingResetComplete) { + mIsAwaitingResetComplete = false; + mCallback->ResetComplete(); + } + if (mIsAwaitingDrainComplete) { + mIsAwaitingDrainComplete = false; + mCallback->DrainComplete(); + } +} + } // namespace gmp } // namespace mozilla diff --git a/dom/media/gmp/GMPVideoDecoderParent.h b/dom/media/gmp/GMPVideoDecoderParent.h index 9b54403146f..1f477ed4176 100644 --- a/dom/media/gmp/GMPVideoDecoderParent.h +++ b/dom/media/gmp/GMPVideoDecoderParent.h @@ -79,9 +79,13 @@ private: Shmem* aMem) override; virtual bool Recv__delete__() override; + void UnblockResetAndDrain(); + bool mIsOpen; bool mShuttingDown; bool mActorDestroyed; + bool mIsAwaitingResetComplete; + bool mIsAwaitingDrainComplete; nsRefPtr mPlugin; GMPVideoDecoderCallbackProxy* mCallback; GMPVideoHostImpl mVideoHost; diff --git a/dom/media/platforms/wrappers/H264Converter.cpp b/dom/media/platforms/wrappers/H264Converter.cpp index 9defd2ac52f..c80d7f71754 100644 --- a/dom/media/platforms/wrappers/H264Converter.cpp +++ b/dom/media/platforms/wrappers/H264Converter.cpp @@ -95,6 +95,7 @@ H264Converter::Drain() if (mDecoder) { return mDecoder->Drain(); } + mCallback->DrainComplete(); return mLastError; } diff --git a/dom/media/webspeech/synth/windows/SapiService.cpp b/dom/media/webspeech/synth/windows/SapiService.cpp index f8753427845..15d4fc095dd 100644 --- a/dom/media/webspeech/synth/windows/SapiService.cpp +++ b/dom/media/webspeech/synth/windows/SapiService.cpp @@ -13,8 +13,6 @@ #include "mozilla/dom/nsSpeechTask.h" #include "mozilla/Preferences.h" -#include - namespace mozilla { namespace dom { @@ -226,9 +224,19 @@ SapiService::RegisterVoices() return false; } + nsRefPtr category; + if (FAILED(CoCreateInstance(CLSID_SpObjectTokenCategory, nullptr, CLSCTX_ALL, + IID_ISpObjectTokenCategory, + getter_AddRefs(category)))) { + return false; + } + if (FAILED(category->SetId(SPCAT_VOICES, FALSE))) { + return false; + } + nsRefPtr voiceTokens; - if (FAILED(SpEnumTokens(SPCAT_VOICES, nullptr, nullptr, - getter_AddRefs(voiceTokens)))) { + if (FAILED(category->EnumTokens(nullptr, nullptr, + getter_AddRefs(voiceTokens)))) { return false; } @@ -238,11 +246,6 @@ SapiService::RegisterVoices() break; } - WCHAR* description = nullptr; - if (FAILED(SpGetDescription(voiceToken, &description))) { - continue; - } - nsRefPtr attributes; if (FAILED(voiceToken->OpenKey(L"Attributes", getter_AddRefs(attributes)))) { @@ -258,9 +261,15 @@ SapiService::RegisterVoices() // name. nsAutoString hexLcid; LCID lcid = wcstol(language, nullptr, 16); + CoTaskMemFree(language); nsAutoString locale; nsWin32Locale::GetXPLocale(lcid, locale); + WCHAR* description = nullptr; + if (FAILED(voiceToken->GetStringValue(nullptr, &description))) { + continue; + } + nsAutoString uri; uri.AssignLiteral("urn:moz-tts:sapi:"); uri.Append(description); @@ -269,6 +278,7 @@ SapiService::RegisterVoices() rv = registry->AddVoice(this, uri, nsDependentString(description), locale, true); + CoTaskMemFree(description); if (NS_FAILED(rv)) { continue; } diff --git a/dom/plugins/base/nsIPluginHost.idl b/dom/plugins/base/nsIPluginHost.idl index d7545812f4a..bfb5bb133e2 100644 --- a/dom/plugins/base/nsIPluginHost.idl +++ b/dom/plugins/base/nsIPluginHost.idl @@ -36,11 +36,11 @@ interface nsIClearSiteDataCallback : nsISupports void callback(in nsresult rv); }; -[scriptable, uuid(2bed7533-50e3-45dd-9e47-102e2c6f5ea8)] +[scriptable, uuid(50677599-323f-4c7d-a450-307bdb7acbf0)] interface nsIPluginHost : nsISupports { /** - * Causes the plugins directory to be searched again for new plugin + * Causes the plugins directory to be searched again for new plugin * libraries. */ void reloadPlugins(); @@ -64,6 +64,7 @@ interface nsIPluginHost : nsISupports */ const uint32_t EXCLUDE_NONE = 0; const uint32_t EXCLUDE_DISABLED = 1 << 0; + const uint32_t EXCLUDE_FAKE = 1 << 1; /* * Clear site data for a given plugin. @@ -127,6 +128,9 @@ interface nsIPluginHost : nsISupports * passed to the permission manager to see whether the plugin is allowed to * run, for example. This will typically be based on the plugin's "nice name" * and its blocklist state. + * + * @mimeType The MIME type we're interested in. + * @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE. */ ACString getPermissionStringForType(in AUTF8String mimeType, [optional] in uint32_t excludeFlags); @@ -136,6 +140,12 @@ interface nsIPluginHost : nsISupports * enabled and disabled/blocklisted plugins, but an enabled plugin will * always be returned if available. * + * A fake plugin tag, if one exists and is available, will be returned in + * preference to NPAPI plugin tags unless excluded by the excludeFlags. + * + * @mimeType The MIME type we're interested in. + * @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE. + * * @throws NS_ERROR_NOT_AVAILABLE if no plugin is available for this MIME * type. */ @@ -145,16 +155,45 @@ interface nsIPluginHost : nsISupports /** * Get the nsIPluginTag enabled state for this MIME type. See * nsIPluginTag.enabledState. + * + * @mimeType The MIME type we're interested in. + * @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE. */ unsigned long getStateForType(in AUTF8String mimeType, [optional] in uint32_t excludeFlags); /** * Get the blocklist state for a MIME type. See nsIPluginTag.blocklistState. + * + * @mimeType The MIME type we're interested in. + * @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE. */ uint32_t getBlocklistStateForType(in AUTF8String aMimeType, [optional] in uint32_t excludeFlags); + /** + * Create a fake plugin tag, register it, and return it. The argument is a + * FakePluginTagInit dictionary. See documentation in + * FakePluginTagInit.webidl for what it should look like. Will throw + * NS_ERROR_UNEXPECTED if there is already a fake plugin registered with the + * given handler URI. + */ + [implicit_jscontext] + nsIFakePluginTag registerFakePlugin(in jsval initDictionary); + + /** + * Get a reference to an existing fake plugin tag for the given MIME type, if + * any. Can return null. + */ + nsIFakePluginTag getFakePlugin(in AUTF8String mimeType); + + /** + * Unregister a fake plugin. The argument can be the .handlerURI.spec of an + * existing nsIFakePluginTag, or just a known handler URI string that was + * passed in the FakePluginTagInit when registering. + */ + void unregisterFakePlugin(in AUTF8String handlerURI); + /** * Returns true if plugins with the given mimetype will run out of process. */ diff --git a/dom/plugins/base/nsIPluginTag.idl b/dom/plugins/base/nsIPluginTag.idl index 41dbb052461..2ab71e324b0 100644 --- a/dom/plugins/base/nsIPluginTag.idl +++ b/dom/plugins/base/nsIPluginTag.idl @@ -5,7 +5,9 @@ #include "nsISupports.idl" -[scriptable, uuid(32563b21-3c5e-4864-baaa-4e49b90b64f2)] +interface nsIURI; + +[scriptable, uuid(5daa99d5-265a-4397-b429-c943803e2619)] interface nsIPluginTag : nsISupports { // enabledState is stored as one of the following as an integer in prefs, @@ -26,6 +28,8 @@ interface nsIPluginTag : nsISupports /** * true only if this plugin is "hardblocked" and cannot be enabled. */ + // FIXME-jsplugins QI to fakePluginTag possible + // FIXME-jsplugins implement missing + tests (whatever that means) readonly attribute boolean blocklisted; /** @@ -55,3 +59,17 @@ interface nsIPluginTag : nsISupports [retval, array, size_is(aCount)] out wstring aResults); }; + +/** + * An interface representing a "fake" plugin: one implemented in JavaScript, not + * as a NPAPI plug-in. See nsIPluginHost.registerFakePlugin and the + * documentation for the FakePluginTagInit dictionary. + */ +[scriptable, uuid(6d22c968-226d-4156-b230-da6ad6bbf6e8)] +interface nsIFakePluginTag : nsIPluginTag +{ + // The URI that should be loaded into the tag (as a frame) to handle the + // plugin. Note that the original data/src value for the plugin is not loaded + // and will need to be requested by the handler via XHR or similar if desired. + readonly attribute nsIURI handlerURI; +}; diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index b0b4269a00a..4f35b147ab7 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -1673,8 +1673,8 @@ nsNPAPIPluginInstance::CarbonNPAPIFailure() static bool GetJavaVersionFromMimetype(nsPluginTag* pluginTag, nsCString& version) { - for (uint32_t i = 0; i < pluginTag->mMimeTypes.Length(); ++i) { - nsCString type = pluginTag->mMimeTypes[i]; + for (uint32_t i = 0; i < pluginTag->MimeTypes().Length(); ++i) { + nsCString type = pluginTag->MimeTypes()[i]; nsAutoCString jpi("application/x-java-applet;jpi-version="); int32_t idx = type.Find(jpi, false, 0, -1); diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp index df5105ea7af..4a157040667 100644 --- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -52,6 +52,7 @@ #include "nsICategoryManager.h" #include "nsPluginStreamListenerPeer.h" #include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/FakePluginTagInitBinding.h" #include "mozilla/LoadInfo.h" #include "mozilla/plugins/PluginAsyncSurrogate.h" #include "mozilla/plugins/PluginBridge.h" @@ -119,6 +120,7 @@ using namespace mozilla; using mozilla::TimeStamp; using mozilla::plugins::PluginTag; using mozilla::plugins::PluginAsyncSurrogate; +using mozilla::dom::FakePluginTagInit; // Null out a strong ref to a linked list iteratively to avoid // exhausting the stack (bug 486349). @@ -230,7 +232,7 @@ nsInvalidPluginTag::~nsInvalidPluginTag() // Helper to check for a MIME in a comma-delimited preference static bool -IsTypeInList(nsCString &aMimeType, nsCString aTypeList) +IsTypeInList(const nsCString& aMimeType, nsCString aTypeList) { nsAutoCString searchStr; searchStr.Assign(','); @@ -998,7 +1000,7 @@ nsPluginHost::TrySetUpPluginInstance(const nsACString &aMimeType, #if defined(MOZ_WIDGET_ANDROID) && defined(MOZ_CRASHREPORTER) if (pluginTag->mIsFlashPlugin) { - CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FlashVersion"), pluginTag->mVersion); + CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FlashVersion"), pluginTag->Version()); } #endif @@ -1049,7 +1051,22 @@ nsPluginHost::HavePluginForType(const nsACString & aMimeType, PluginFilter aFilter) { bool checkEnabled = aFilter & eExcludeDisabled; - return FindNativePluginForType(aMimeType, checkEnabled); + bool allowFake = !(aFilter & eExcludeFake); + return FindPluginForType(aMimeType, allowFake, checkEnabled); +} + +nsIInternalPluginTag* +nsPluginHost::FindPluginForType(const nsACString& aMimeType, + bool aIncludeFake, bool aCheckEnabled) +{ + if (aIncludeFake) { + nsFakePluginTag* fakeTag = FindFakePluginForType(aMimeType, aCheckEnabled); + if (fakeTag) { + return fakeTag; + } + } + + return FindNativePluginForType(aMimeType, aCheckEnabled); } NS_IMETHODIMP @@ -1057,21 +1074,22 @@ nsPluginHost::GetPluginTagForType(const nsACString& aMimeType, uint32_t aExcludeFlags, nsIPluginTag** aResult) { + bool includeFake = !(aExcludeFlags & eExcludeFake); bool includeDisabled = !(aExcludeFlags & eExcludeDisabled); - nsPluginTag *tag = FindNativePluginForType(aMimeType, true); - - // Prefer enabled, but select disabled if none is found - if (includeDisabled && !tag) { - tag = FindNativePluginForType(aMimeType, false); + // First look for an enabled plugin. + nsRefPtr tag = FindPluginForType(aMimeType, includeFake, + true); + if (!tag && includeDisabled) { + tag = FindPluginForType(aMimeType, includeFake, false); } - if (!tag) { - return NS_ERROR_NOT_AVAILABLE; + if (tag) { + tag.forget(aResult); + return NS_OK; } - NS_ADDREF(*aResult = tag); - return NS_OK; + return NS_ERROR_NOT_AVAILABLE; } NS_IMETHODIMP @@ -1152,17 +1170,28 @@ nsPluginHost::HavePluginForExtension(const nsACString & aExtension, PluginFilter aFilter) { bool checkEnabled = aFilter & eExcludeDisabled; - return FindNativePluginForExtension(aExtension, aMimeType, checkEnabled); + bool allowFake = !(aFilter & eExcludeFake); + return FindNativePluginForExtension(aExtension, aMimeType, checkEnabled) || + (allowFake && + FindFakePluginForExtension(aExtension, aMimeType, checkEnabled)); } void -nsPluginHost::GetPlugins(nsTArray >& aPluginArray, +nsPluginHost::GetPlugins(nsTArray>& aPluginArray, bool aIncludeDisabled) { aPluginArray.Clear(); LoadPlugins(); + // Append fake plugins, then normal plugins. + + uint32_t numFake = mFakePlugins.Length(); + for (uint32_t i = 0; i < numFake; i++) { + aPluginArray.AppendElement(mFakePlugins[i]); + } + + // Regular plugins nsPluginTag* plugin = mPlugins; while (plugin != nullptr) { if (plugin->IsEnabled() || aIncludeDisabled) { @@ -1172,12 +1201,14 @@ nsPluginHost::GetPlugins(nsTArray >& aPluginArray, } } +// FIXME-jsplugins Check users for order of fake v non-fake NS_IMETHODIMP nsPluginHost::GetPluginTags(uint32_t* aPluginCount, nsIPluginTag*** aResults) { LoadPlugins(); uint32_t count = 0; + uint32_t fakeCount = mFakePlugins.Length(); nsRefPtr plugin = mPlugins; while (plugin != nullptr) { count++; @@ -1185,11 +1216,11 @@ nsPluginHost::GetPluginTags(uint32_t* aPluginCount, nsIPluginTag*** aResults) } *aResults = static_cast - (moz_xmalloc(count * sizeof(**aResults))); + (moz_xmalloc((fakeCount + count) * sizeof(**aResults))); if (!*aResults) return NS_ERROR_OUT_OF_MEMORY; - *aPluginCount = count; + *aPluginCount = count + fakeCount; plugin = mPlugins; for (uint32_t i = 0; i < count; i++) { @@ -1198,6 +1229,11 @@ nsPluginHost::GetPluginTags(uint32_t* aPluginCount, nsIPluginTag*** aResults) plugin = plugin->mNext; } + for (uint32_t i = 0; i < fakeCount; i++) { + (*aResults)[i + count] = static_cast(mFakePlugins[i]); + NS_ADDREF((*aResults)[i + count]); + } + return NS_OK; } @@ -1217,7 +1253,7 @@ nsPluginHost::FindPreferredPlugin(const InfallibleTArray& matches) nsPluginTag *preferredPlugin = matches[0]; for (unsigned int i = 1; i < matches.Length(); i++) { - if (mozilla::Version(matches[i]->mVersion.get()) > preferredPlugin->mVersion.get()) { + if (mozilla::Version(matches[i]->Version().get()) > preferredPlugin->Version().get()) { preferredPlugin = matches[i]; } } @@ -1225,6 +1261,47 @@ nsPluginHost::FindPreferredPlugin(const InfallibleTArray& matches) return preferredPlugin; } +nsFakePluginTag* +nsPluginHost::FindFakePluginForExtension(const nsACString & aExtension, + /* out */ nsACString & aMimeType, + bool aCheckEnabled) +{ + if (aExtension.IsEmpty()) { + return nullptr; + } + + int32_t numFakePlugins = mFakePlugins.Length(); + for (int32_t i = 0; i < numFakePlugins; i++) { + nsFakePluginTag *plugin = mFakePlugins[i]; + bool active; + if ((!aCheckEnabled || + (NS_SUCCEEDED(plugin->GetActive(&active)) && active)) && + plugin->HasExtension(aExtension, aMimeType)) { + return plugin; + } + } + + return nullptr; +} + +nsFakePluginTag* +nsPluginHost::FindFakePluginForType(const nsACString & aMimeType, + bool aCheckEnabled) +{ + int32_t numFakePlugins = mFakePlugins.Length(); + for (int32_t i = 0; i < numFakePlugins; i++) { + nsFakePluginTag *plugin = mFakePlugins[i]; + bool active; + if ((!aCheckEnabled || + (NS_SUCCEEDED(plugin->GetActive(&active)) && active)) && + plugin->HasMimeType(aMimeType)) { + return plugin; + } + } + + return nullptr; +} + nsPluginTag* nsPluginHost::FindNativePluginForType(const nsACString & aMimeType, bool aCheckEnabled) @@ -1411,12 +1488,12 @@ nsresult nsPluginHost::GetPlugin(const nsACString &aMimeType, rv = NS_OK; PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsPluginHost::GetPlugin Begin mime=%s, plugin=%s\n", - PromiseFlatCString(aMimeType).get(), pluginTag->mFileName.get())); + PromiseFlatCString(aMimeType).get(), pluginTag->FileName().get())); #ifdef DEBUG - if (!pluginTag->mFileName.IsEmpty()) + if (!pluginTag->FileName().IsEmpty()) printf("For %s found plugin %s\n", - PromiseFlatCString(aMimeType).get(), pluginTag->mFileName.get()); + PromiseFlatCString(aMimeType).get(), pluginTag->FileName().get()); #endif rv = EnsurePluginLoaded(pluginTag); @@ -1431,7 +1508,7 @@ nsresult nsPluginHost::GetPlugin(const nsACString &aMimeType, PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsPluginHost::GetPlugin End mime=%s, rv=%d, plugin=%p name=%s\n", PromiseFlatCString(aMimeType).get(), rv, *aPlugin, - (pluginTag ? pluginTag->mFileName.get() : "(not found)"))); + (pluginTag ? pluginTag->FileName().get() : "(not found)"))); return rv; } @@ -1531,6 +1608,50 @@ nsPluginHost::EnumerateSiteData(const nsACString& domain, return NS_OK; } +NS_IMETHODIMP +nsPluginHost::RegisterFakePlugin(JS::Handle aInitDictionary, + JSContext* aCx, + nsIFakePluginTag **aResult) +{ + FakePluginTagInit initDictionary; + if (!initDictionary.Init(aCx, aInitDictionary)) { + return NS_ERROR_FAILURE; + } + + nsRefPtr newTag; + nsresult rv = nsFakePluginTag::Create(initDictionary, getter_AddRefs(newTag)); + NS_ENSURE_SUCCESS(rv, rv); + + for (auto existingTag : mFakePlugins) { + if (newTag->HandlerURIMatches(existingTag->HandlerURI())) { + return NS_ERROR_UNEXPECTED; + } + } + + mFakePlugins.AppendElement(newTag); + // FIXME-jsplugins do we need to register with the category manager here? For + // shumway, for now, probably not. + newTag.forget(aResult); + return NS_OK; +} + +NS_IMETHODIMP +nsPluginHost::UnregisterFakePlugin(const nsACString& aHandlerURI) +{ + nsCOMPtr handlerURI; + nsresult rv = NS_NewURI(getter_AddRefs(handlerURI), aHandlerURI); + NS_ENSURE_SUCCESS(rv, rv); + + for (uint32_t i = 0; i < mFakePlugins.Length(); ++i) { + if (mFakePlugins[i]->HandlerURIMatches(handlerURI)) { + mFakePlugins.RemoveElementAt(i); + return NS_OK; + } + } + + return NS_OK; +} + NS_IMETHODIMP nsPluginHost::RegisterPlayPreviewMimeType(const nsACString& mimeType, bool ignoreCTP, @@ -1583,6 +1704,21 @@ nsPluginHost::GetPlayPreviewInfo(const nsACString& mimeType, return NS_ERROR_NOT_AVAILABLE; } +// FIXME-jsplugins Is this method actually needed? +NS_IMETHODIMP +nsPluginHost::GetFakePlugin(const nsACString & aMimeType, + nsIFakePluginTag** aResult) +{ + nsRefPtr result = FindFakePluginForType(aMimeType, false); + if (result) { + result.forget(aResult); + return NS_OK; + } + + *aResult = nullptr; + return NS_ERROR_NOT_AVAILABLE; +} + #define ClearDataFromSitesClosure_CID {0x9fb21761, 0x2403, 0x41ad, {0x9e, 0xfd, 0x36, 0x7e, 0xc4, 0x4f, 0xa4, 0x5e}} @@ -1649,6 +1785,7 @@ NS_INTERFACE_MAP_BEGIN(ClearDataFromSitesClosure) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIClearSiteDataCallback) NS_INTERFACE_MAP_END +// FIXME-jsplugins what should this do for fake plugins? NS_IMETHODIMP nsPluginHost::ClearSiteData(nsIPluginTag* plugin, const nsACString& domain, uint64_t flags, int64_t maxAge, nsIClearSiteDataCallback* callbackFunc) @@ -1836,15 +1973,24 @@ nsPluginHost::GetSpecialType(const nsACString & aMIMEType) bool nsPluginHost::IsLiveTag(nsIPluginTag* aPluginTag) { + nsCOMPtr internalTag(do_QueryInterface(aPluginTag)); + uint32_t fakeCount = mFakePlugins.Length(); + for (uint32_t i = 0; i < fakeCount; i++) { + if (mFakePlugins[i] == internalTag) { + return true; + } + } + nsPluginTag* tag; for (tag = mPlugins; tag; tag = tag->mNext) { - if (tag == aPluginTag) { + if (tag == internalTag) { return true; } } return false; } +// FIXME-jsplugins what should happen with jsplugins here, if anything? nsPluginTag* nsPluginHost::HaveSamePlugin(const nsPluginTag* aPluginTag) { @@ -1856,6 +2002,8 @@ nsPluginHost::HaveSamePlugin(const nsPluginTag* aPluginTag) return nullptr; } +// Don't have to worry about fake plugins here, since this is only used during +// the plugin directory scan, which doesn't pick up fake plugins. nsPluginTag* nsPluginHost::FirstPluginWithPath(const nsCString& path) { @@ -1970,7 +2118,7 @@ nsPluginHost::ShouldAddPlugin(nsPluginTag* aPluginTag) #if defined(XP_WIN) && (defined(__x86_64__) || defined(_M_X64)) // On 64-bit windows, the only plugin we should load is flash. Use library // filename and MIME type to check. - if (StringBeginsWith(aPluginTag->mFileName, NS_LITERAL_CSTRING("NPSWF"), nsCaseInsensitiveCStringComparator()) && + if (StringBeginsWith(aPluginTag->FileName(), NS_LITERAL_CSTRING("NPSWF"), nsCaseInsensitiveCStringComparator()) && (aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-shockwave-flash")) || aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-shockwave-flash-test")))) { return true; @@ -1983,7 +2131,7 @@ nsPluginHost::ShouldAddPlugin(nsPluginTag* aPluginTag) } #ifdef PLUGIN_LOGGING PLUGIN_LOG(PLUGIN_LOG_NORMAL, - ("ShouldAddPlugin : Ignoring non-flash plugin library %s\n", aPluginTag->mFileName.get())); + ("ShouldAddPlugin : Ignoring non-flash plugin library %s\n", aPluginTag->FileName().get())); #endif // PLUGIN_LOGGING return false; #else @@ -2003,9 +2151,9 @@ nsPluginHost::AddPluginTag(nsPluginTag* aPluginTag) if (aPluginTag->IsActive()) { nsAdoptingCString disableFullPage = Preferences::GetCString(kPrefDisableFullPage); - for (uint32_t i = 0; i < aPluginTag->mMimeTypes.Length(); i++) { - if (!IsTypeInList(aPluginTag->mMimeTypes[i], disableFullPage)) { - RegisterWithCategoryManager(aPluginTag->mMimeTypes[i], + for (uint32_t i = 0; i < aPluginTag->MimeTypes().Length(); i++) { + if (!IsTypeInList(aPluginTag->MimeTypes()[i], disableFullPage)) { + RegisterWithCategoryManager(aPluginTag->MimeTypes()[i], ePluginRegister); } } @@ -2590,11 +2738,23 @@ nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch, return; } - nsTArray> plugins; + nsTArray> plugins; GetPlugins(plugins, true); for (size_t i = 0; i < plugins.Length(); i++) { - nsRefPtr tag = plugins[i]; + nsCOMPtr basetag = plugins[i]; + + nsCOMPtr faketag = do_QueryInterface(basetag); + if (faketag) { + /// FIXME-jsplugins - We need to make content processes properly + /// aware of jsplugins (and add a nsIInternalPluginTag->AsNative() to + /// avoid this hacky static cast) + continue; + } + + /// FIXME-jsplugins - We need to cleanup the various plugintag classes + /// to be more sane and avoid this dance + nsPluginTag *tag = static_cast(basetag.get()); if (!nsNPAPIPlugin::RunPluginOOP(tag)) { // Don't expose non-OOP plugins to content processes since we have no way @@ -2603,20 +2763,21 @@ nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch, } aPlugins->AppendElement(PluginTag(tag->mId, - tag->mName, - tag->mDescription, - tag->mMimeTypes, - tag->mMimeDescriptions, - tag->mExtensions, + tag->Name(), + tag->Description(), + tag->MimeTypes(), + tag->MimeDescriptions(), + tag->Extensions(), tag->mIsJavaPlugin, tag->mIsFlashPlugin, - tag->mFileName, - tag->mVersion, + tag->FileName(), + tag->Version(), tag->mLastModifiedTime, tag->IsFromExtension())); } } +// This function is not relevant for fake plugins. void nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag) { @@ -2634,18 +2795,18 @@ nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag) // Update types with category manager nsAdoptingCString disableFullPage = Preferences::GetCString(kPrefDisableFullPage); - for (uint32_t i = 0; i < aPluginTag->mMimeTypes.Length(); i++) { + for (uint32_t i = 0; i < aPluginTag->MimeTypes().Length(); i++) { nsRegisterType shouldRegister; - if (IsTypeInList(aPluginTag->mMimeTypes[i], disableFullPage)) { + if (IsTypeInList(aPluginTag->MimeTypes()[i], disableFullPage)) { shouldRegister = ePluginUnregister; } else { - nsPluginTag *plugin = FindNativePluginForType(aPluginTag->mMimeTypes[i], + nsPluginTag *plugin = FindNativePluginForType(aPluginTag->MimeTypes()[i], true); shouldRegister = plugin ? ePluginRegister : ePluginUnregister; } - RegisterWithCategoryManager(aPluginTag->mMimeTypes[i], shouldRegister); + RegisterWithCategoryManager(aPluginTag->MimeTypes()[i], shouldRegister); } nsCOMPtr obsService = @@ -2666,7 +2827,7 @@ nsPluginHost::IsTypeWhitelisted(const char *aMimeType) } void -nsPluginHost::RegisterWithCategoryManager(nsCString &aMimeType, +nsPluginHost::RegisterWithCategoryManager(const nsCString& aMimeType, nsRegisterType aType) { PLUGIN_LOG(PLUGIN_LOG_NORMAL, @@ -2690,6 +2851,15 @@ nsPluginHost::RegisterWithCategoryManager(nsCString &aMimeType, mOverrideInternalTypes, nullptr); } else { + if (aType == ePluginMaybeUnregister) { + // Bail out if this type is still used by an enabled plugin + if (HavePluginForType(aMimeType)) { + return; + } + } else { + MOZ_ASSERT(aType == ePluginUnregister, "Unknown nsRegisterType"); + } + // Only delete the entry if a plugin registered for it nsXPIDLCString value; nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", @@ -2768,13 +2938,13 @@ nsPluginHost::WritePluginInfo() // filename & fullpath are on separate line // because they can contain field delimiter char PR_fprintf(fd, "%s%c%c\n%s%c%c\n%s%c%c\n", - (tag->mFileName.get()), + (tag->FileName().get()), PLUGIN_REGISTRY_FIELD_DELIMITER, PLUGIN_REGISTRY_END_OF_LINE_MARKER, (tag->mFullPath.get()), PLUGIN_REGISTRY_FIELD_DELIMITER, PLUGIN_REGISTRY_END_OF_LINE_MARKER, - (tag->mVersion.get()), + (tag->Version().get()), PLUGIN_REGISTRY_FIELD_DELIMITER, PLUGIN_REGISTRY_END_OF_LINE_MARKER); @@ -2792,23 +2962,23 @@ nsPluginHost::WritePluginInfo() //description, name & mtypecount are on separate line PR_fprintf(fd, "%s%c%c\n%s%c%c\n%d\n", - (tag->mDescription.get()), + (tag->Description().get()), PLUGIN_REGISTRY_FIELD_DELIMITER, PLUGIN_REGISTRY_END_OF_LINE_MARKER, - (tag->mName.get()), + (tag->Name().get()), PLUGIN_REGISTRY_FIELD_DELIMITER, PLUGIN_REGISTRY_END_OF_LINE_MARKER, - tag->mMimeTypes.Length()); + tag->MimeTypes().Length()); // Add in each mimetype this plugin supports - for (uint32_t i = 0; i < tag->mMimeTypes.Length(); i++) { + for (uint32_t i = 0; i < tag->MimeTypes().Length(); i++) { PR_fprintf(fd, "%d%c%s%c%s%c%s%c%c\n", i,PLUGIN_REGISTRY_FIELD_DELIMITER, - (tag->mMimeTypes[i].get()), + (tag->MimeTypes()[i].get()), PLUGIN_REGISTRY_FIELD_DELIMITER, - (tag->mMimeDescriptions[i].get()), + (tag->MimeDescriptions()[i].get()), PLUGIN_REGISTRY_FIELD_DELIMITER, - (tag->mExtensions[i].get()), + (tag->Extensions()[i].get()), PLUGIN_REGISTRY_FIELD_DELIMITER, PLUGIN_REGISTRY_END_OF_LINE_MARKER); } @@ -3153,7 +3323,7 @@ nsPluginHost::ReadPluginInfo() } MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC, - ("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->mFileName.get())); + ("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->FileName().get())); if (!ShouldAddPlugin(tag)) { continue; @@ -3881,7 +4051,7 @@ nsPluginHost::GetPluginName(nsNPAPIPluginInstance *aPluginInstance, if (!plugin) return NS_ERROR_FAILURE; - *aPluginName = TagForPlugin(plugin)->mName.get(); + *aPluginName = TagForPlugin(plugin)->Name().get(); return NS_OK; } diff --git a/dom/plugins/base/nsPluginHost.h b/dom/plugins/base/nsPluginHost.h index cf4170b5ce6..d47d9ef09b7 100644 --- a/dom/plugins/base/nsPluginHost.h +++ b/dom/plugins/base/nsPluginHost.h @@ -12,6 +12,7 @@ #include "prlink.h" #include "prclist.h" #include "nsIPluginTag.h" +#include "nsPluginPlayPreviewInfo.h" #include "nsPluginsDir.h" #include "nsPluginDirServiceProvider.h" #include "nsAutoPtr.h" @@ -23,7 +24,6 @@ #include "nsTObserverArray.h" #include "nsITimer.h" #include "nsPluginTags.h" -#include "nsPluginPlayPreviewInfo.h" #include "nsIEffectiveTLDService.h" #include "nsIIDNService.h" #include "nsCRT.h" @@ -79,6 +79,7 @@ class nsPluginHost final : public nsIPluginHost, public nsSupportsWeakReference { friend class nsPluginTag; + friend class nsFakePluginTag; virtual ~nsPluginHost(); public: @@ -103,7 +104,8 @@ public: // Acts like a bitfield enum PluginFilter { eExcludeNone = nsIPluginHost::EXCLUDE_NONE, - eExcludeDisabled = nsIPluginHost::EXCLUDE_DISABLED + eExcludeDisabled = nsIPluginHost::EXCLUDE_DISABLED, + eExcludeFake = nsIPluginHost::EXCLUDE_FAKE }; // FIXME-jsplugins comment about fake bool HavePluginForType(const nsACString & aMimeType, @@ -114,7 +116,7 @@ public: /* out */ nsACString & aMimeType, PluginFilter aFilter = eExcludeDisabled); - void GetPlugins(nsTArray >& aPluginArray, + void GetPlugins(nsTArray>& aPluginArray, bool aIncludeDisabled = false); void FindPluginsForContent(uint32_t aPluginEpoch, @@ -266,11 +268,32 @@ private: nsPluginTag* FindPreferredPlugin(const InfallibleTArray& matches); - // Return an nsPluginTag for this type, if any. If aCheckEnabled is - // true, only enabled plugins will be returned. + // Find a plugin for the given type. If aIncludeFake is true a fake plugin + // will be preferred if one exists; otherwise a fake plugin will never be + // returned. If aCheckEnabled is false, disabled plugins can be returned. + nsIInternalPluginTag* FindPluginForType(const nsACString& aMimeType, + bool aIncludeFake, bool aCheckEnabled); + + // Find specifically a fake plugin for the given type. If aCheckEnabled is + // false, disabled plugins can be returned. + nsFakePluginTag* FindFakePluginForType(const nsACString & aMimeType, + bool aCheckEnabled); + + // Find specifically a fake plugin for the given extension. If aCheckEnabled + // is false, disabled plugins can be returned. aMimeType will be filled in + // with the MIME type the plugin is registered for. + nsFakePluginTag* FindFakePluginForExtension(const nsACString & aExtension, + /* out */ nsACString & aMimeType, + bool aCheckEnabled); + + // Find specifically a native (NPAPI) plugin for the given type. If + // aCheckEnabled is false, disabled plugins can be returned. nsPluginTag* FindNativePluginForType(const nsACString & aMimeType, bool aCheckEnabled); + // Find specifically a native (NPAPI) plugin for the given extension. If + // aCheckEnabled is false, disabled plugins can be returned. aMimeType will + // be filled in with the MIME type the plugin is registered for. nsPluginTag* FindNativePluginForExtension(const nsACString & aExtension, /* out */ nsACString & aMimeType, bool aCheckEnabled); @@ -285,9 +308,12 @@ private: // FIXME revisit, no ns prefix // Registers or unregisters the given mime type with the category manager - // (performs no checks - see UpdateCategoryManager) - enum nsRegisterType { ePluginRegister, ePluginUnregister }; - void RegisterWithCategoryManager(nsCString &aMimeType, nsRegisterType aType); + enum nsRegisterType { ePluginRegister, + ePluginUnregister, + // Checks if this type should still be registered first + ePluginMaybeUnregister }; + void RegisterWithCategoryManager(const nsCString& aMimeType, + nsRegisterType aType); void AddPluginTag(nsPluginTag* aPluginTag); @@ -348,6 +374,9 @@ private: nsRefPtr mCachedPlugins; nsRefPtr mInvalidPlugins; nsTArray< nsRefPtr > mPlayPreviewMimeTypes; + + nsTArray< nsRefPtr > mFakePlugins; + bool mPluginsLoaded; // set by pref plugin.override_internal_types diff --git a/dom/plugins/base/nsPluginTags.cpp b/dom/plugins/base/nsPluginTags.cpp index 061042d40ba..5d48c2a11f3 100644 --- a/dom/plugins/base/nsPluginTags.cpp +++ b/dom/plugins/base/nsPluginTags.cpp @@ -18,11 +18,14 @@ #include "nsCharSeparatedTokenizer.h" #include "mozilla/Preferences.h" #include "mozilla/unused.h" +#include "nsNetUtil.h" #include #include "mozilla/dom/EncodingUtils.h" #include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/FakePluginTagInitBinding.h" using mozilla::dom::EncodingUtils; +using mozilla::dom::FakePluginTagInit; using namespace mozilla; // These legacy flags are used in the plugin registry. The states are now @@ -98,14 +101,24 @@ MakeNiceFileName(const nsCString & aFileName) } static nsCString -MakePrefNameForPlugin(const char* const subname, nsPluginTag* aTag) +MakePrefNameForPlugin(const char* const subname, nsIInternalPluginTag* aTag) { nsCString pref; + nsAutoCString pluginName(aTag->GetNiceFileName()); + + if (pluginName.IsEmpty()) { + // Use filename if nice name fails + pluginName = aTag->FileName(); + if (pluginName.IsEmpty()) { + MOZ_ASSERT_UNREACHABLE("Plugin with no filename or nice name in list"); + pluginName.AssignLiteral("unknown-plugin-name"); + } + } pref.AssignLiteral("plugin."); pref.Append(subname); pref.Append('.'); - pref.Append(aTag->GetNiceFileName()); + pref.Append(pluginName); return pref; } @@ -134,11 +147,79 @@ CStringArrayToXPCArray(nsTArray & aArray, } static nsCString -GetStatePrefNameForPlugin(nsPluginTag* aTag) +GetStatePrefNameForPlugin(nsIInternalPluginTag* aTag) { return MakePrefNameForPlugin("state", aTag); } +static nsresult +IsEnabledStateLockedForPlugin(nsIInternalPluginTag* aTag, + bool* aIsEnabledStateLocked) +{ + *aIsEnabledStateLocked = false; + nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); + + if (NS_WARN_IF(!prefs)) { + return NS_ERROR_FAILURE; + } + + unused << prefs->PrefIsLocked(GetStatePrefNameForPlugin(aTag).get(), + aIsEnabledStateLocked); + + return NS_OK; +} + +/* nsIInternalPluginTag */ +nsIInternalPluginTag::nsIInternalPluginTag() +{ +} + +nsIInternalPluginTag::nsIInternalPluginTag(const char* aName, + const char* aDescription, + const char* aFileName, + const char* aVersion) + : mName(aName) + , mDescription(aDescription) + , mFileName(aFileName) + , mVersion(aVersion) +{ +} + +nsIInternalPluginTag::nsIInternalPluginTag(const char* aName, + const char* aDescription, + const char* aFileName, + const char* aVersion, + const nsTArray& aMimeTypes, + const nsTArray& aMimeDescriptions, + const nsTArray& aExtensions) + : mName(aName) + , mDescription(aDescription) + , mFileName(aFileName) + , mVersion(aVersion) + , mMimeTypes(aMimeTypes) + , mMimeDescriptions(aMimeDescriptions) + , mExtensions(aExtensions) +{ +} + +nsIInternalPluginTag::~nsIInternalPluginTag() +{ +} + +bool +nsIInternalPluginTag::HasExtension(const nsACString& aExtension, + nsACString& aMatchingType) const +{ + return SearchExtensions(mExtensions, mMimeTypes, aExtension, aMatchingType); +} + +bool +nsIInternalPluginTag::HasMimeType(const nsACString& aMimeType) const +{ + return mMimeTypes.Contains(aMimeType, + nsCaseInsensitiveCStringArrayComparator()); +} + /* nsPluginTag */ uint32_t nsPluginTag::sNextId; @@ -146,17 +227,15 @@ uint32_t nsPluginTag::sNextId; nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo, int64_t aLastModifiedTime, bool fromExtension) - : mId(sNextId++), + : nsIInternalPluginTag(aPluginInfo->fName, aPluginInfo->fDescription, + aPluginInfo->fFileName, aPluginInfo->fVersion), + mId(sNextId++), mContentProcessRunningCount(0), mHadLocalInstance(false), - mName(aPluginInfo->fName), - mDescription(aPluginInfo->fDescription), mLibrary(nullptr), mIsJavaPlugin(false), mIsFlashPlugin(false), - mFileName(aPluginInfo->fFileName), mFullPath(aPluginInfo->fFullPath), - mVersion(aPluginInfo->fVersion), mLastModifiedTime(aLastModifiedTime), mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED), mCachedBlocklistStateValid(false), @@ -182,16 +261,13 @@ nsPluginTag::nsPluginTag(const char* aName, int64_t aLastModifiedTime, bool fromExtension, bool aArgsAreUTF8) - : mId(sNextId++), + : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion), + mId(sNextId++), mContentProcessRunningCount(0), - mName(aName), - mDescription(aDescription), mLibrary(nullptr), mIsJavaPlugin(false), mIsFlashPlugin(false), - mFileName(aFileName), mFullPath(aFullPath), - mVersion(aVersion), mLastModifiedTime(aLastModifiedTime), mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED), mCachedBlocklistStateValid(false), @@ -217,18 +293,13 @@ nsPluginTag::nsPluginTag(uint32_t aId, bool aIsFlashPlugin, int64_t aLastModifiedTime, bool aFromExtension) - : mId(aId), + : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion, aMimeTypes, + aMimeDescriptions, aExtensions), + mId(aId), mContentProcessRunningCount(0), - mName(aName), - mDescription(aDescription), - mMimeTypes(aMimeTypes), - mMimeDescriptions(aMimeDescriptions), - mExtensions(aExtensions), mLibrary(nullptr), mIsJavaPlugin(aIsJavaPlugin), mIsFlashPlugin(aIsFlashPlugin), - mFileName(aFileName), - mVersion(aVersion), mLastModifiedTime(aLastModifiedTime), mNiceFileName(), mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED), @@ -242,7 +313,7 @@ nsPluginTag::~nsPluginTag() NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349"); } -NS_IMPL_ISUPPORTS(nsPluginTag, nsIPluginTag) +NS_IMPL_ISUPPORTS(nsPluginTag, nsIPluginTag, nsIInternalPluginTag) void nsPluginTag::InitMime(const char* const* aMimeTypes, const char* const* aMimeDescriptions, @@ -472,17 +543,7 @@ nsPluginTag::GetBlocklisted(bool* aBlocklisted) NS_IMETHODIMP nsPluginTag::GetIsEnabledStateLocked(bool* aIsEnabledStateLocked) { - *aIsEnabledStateLocked = false; - nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); - - if (NS_WARN_IF(!prefs)) { - return NS_ERROR_FAILURE; - } - - unused << prefs->PrefIsLocked(GetStatePrefNameForPlugin(this).get(), - aIsEnabledStateLocked); - - return NS_OK; + return IsEnabledStateLockedForPlugin(this, aIsEnabledStateLocked); } bool @@ -606,7 +667,9 @@ void nsPluginTag::TryUnloadPlugin(bool inShutdown) } } -nsCString nsPluginTag::GetNiceFileName() { +const nsCString& +nsPluginTag::GetNiceFileName() +{ if (!mNiceFileName.IsEmpty()) { return mNiceFileName; } @@ -682,20 +745,6 @@ nsPluginTag::GetBlocklistState(uint32_t *aResult) #endif // defined(MOZ_WIDGET_ANDROID) } -bool -nsPluginTag::HasMimeType(const nsACString & aMimeType) const -{ - return mMimeTypes.Contains(aMimeType, - nsCaseInsensitiveCStringArrayComparator()); -} - -bool -nsPluginTag::HasExtension(const nsACString & aExtension, - nsACString & aMatchingType) const -{ - return SearchExtensions(mExtensions, mMimeTypes, aExtension, aMatchingType); -} - void nsPluginTag::InvalidateBlocklistState() { @@ -714,3 +763,220 @@ bool nsPluginTag::IsFromExtension() const { return mIsFromExtension; } + +/* nsFakePluginTag */ + +nsFakePluginTag::nsFakePluginTag() + : mState(nsPluginTag::ePluginState_Disabled) +{ +} + +nsFakePluginTag::~nsFakePluginTag() +{ +} + +NS_IMPL_ADDREF(nsFakePluginTag) +NS_IMPL_RELEASE(nsFakePluginTag) +NS_INTERFACE_TABLE_HEAD(nsFakePluginTag) + NS_INTERFACE_TABLE_BEGIN + NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsFakePluginTag, nsIPluginTag, + nsIInternalPluginTag) + NS_INTERFACE_TABLE_ENTRY(nsFakePluginTag, nsIInternalPluginTag) + NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsFakePluginTag, nsISupports, + nsIInternalPluginTag) + NS_INTERFACE_TABLE_ENTRY(nsFakePluginTag, nsIFakePluginTag) + NS_INTERFACE_TABLE_END +NS_INTERFACE_TABLE_TAIL + +/* static */ +nsresult +nsFakePluginTag::Create(const FakePluginTagInit& aInitDictionary, + nsFakePluginTag** aPluginTag) +{ + NS_ENSURE_TRUE(!aInitDictionary.mMimeEntries.IsEmpty(), NS_ERROR_INVALID_ARG); + + nsRefPtr tag = new nsFakePluginTag(); + nsresult rv = NS_NewURI(getter_AddRefs(tag->mHandlerURI), + aInitDictionary.mHandlerURI); + NS_ENSURE_SUCCESS(rv, rv); + + CopyUTF16toUTF8(aInitDictionary.mNiceName, tag->mNiceName); + CopyUTF16toUTF8(aInitDictionary.mFullPath, tag->mFullPath); + CopyUTF16toUTF8(aInitDictionary.mName, tag->mName); + CopyUTF16toUTF8(aInitDictionary.mDescription, tag->mDescription); + CopyUTF16toUTF8(aInitDictionary.mFileName, tag->mFileName); + CopyUTF16toUTF8(aInitDictionary.mVersion, tag->mVersion); + + for (const FakePluginMimeEntry& mimeEntry : aInitDictionary.mMimeEntries) { + CopyUTF16toUTF8(mimeEntry.mType, *tag->mMimeTypes.AppendElement()); + CopyUTF16toUTF8(mimeEntry.mDescription, + *tag->mMimeDescriptions.AppendElement()); + CopyUTF16toUTF8(mimeEntry.mExtension, *tag->mExtensions.AppendElement()); + } + + tag.forget(aPluginTag); + return NS_OK; +} + +bool +nsFakePluginTag::HandlerURIMatches(nsIURI* aURI) +{ + bool equals = false; + return NS_SUCCEEDED(mHandlerURI->Equals(aURI, &equals)) && equals; +} + +NS_IMETHODIMP +nsFakePluginTag::GetHandlerURI(nsIURI **aResult) +{ + NS_IF_ADDREF(*aResult = mHandlerURI); + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetDescription(/* utf-8 */ nsACString& aResult) +{ + aResult = mDescription; + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetFilename(/* utf-8 */ nsACString& aResult) +{ + aResult = mFileName; + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetFullpath(/* utf-8 */ nsACString& aResult) +{ + aResult = mFullPath; + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetVersion(/* utf-8 */ nsACString& aResult) +{ + aResult = mVersion; + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetName(/* utf-8 */ nsACString& aResult) +{ + aResult = mName; + return NS_OK; +} + +const nsCString& +nsFakePluginTag::GetNiceFileName() +{ + // We don't try to mimic the special-cased flash/java names if the fake plugin + // claims one of their MIME types, but do allow directly setting niceName if + // emulating those is desired. + if (mNiceName.IsEmpty() && !mFileName.IsEmpty()) { + mNiceName = MakeNiceFileName(mFileName); + } + + return mNiceName; +} + +NS_IMETHODIMP +nsFakePluginTag::GetNiceName(/* utf-8 */ nsACString& aResult) +{ + aResult = GetNiceFileName(); + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetBlocklistState(uint32_t* aResult) +{ + // Fake tags don't currently support blocklisting + *aResult = nsIBlocklistService::STATE_NOT_BLOCKED; + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetBlocklisted(bool* aBlocklisted) +{ + // Fake tags can't be blocklisted + *aBlocklisted = false; + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetIsEnabledStateLocked(bool* aIsEnabledStateLocked) +{ + return IsEnabledStateLockedForPlugin(this, aIsEnabledStateLocked); +} + +bool +nsFakePluginTag::IsEnabled() +{ + return mState == nsPluginTag::ePluginState_Enabled || + mState == nsPluginTag::ePluginState_Clicktoplay; +} + +NS_IMETHODIMP +nsFakePluginTag::GetDisabled(bool* aDisabled) +{ + *aDisabled = !IsEnabled(); + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetClicktoplay(bool* aClicktoplay) +{ + *aClicktoplay = (mState == nsPluginTag::ePluginState_Clicktoplay); + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetEnabledState(uint32_t* aEnabledState) +{ + *aEnabledState = (uint32_t)mState; + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::SetEnabledState(uint32_t aEnabledState) +{ + // There are static asserts above enforcing that this enum matches + mState = (nsPluginTag::PluginState)aEnabledState; + // FIXME-jsplugins update + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetMimeTypes(uint32_t* aCount, char16_t*** aResults) +{ + return CStringArrayToXPCArray(mMimeTypes, aCount, aResults); +} + +NS_IMETHODIMP +nsFakePluginTag::GetMimeDescriptions(uint32_t* aCount, char16_t*** aResults) +{ + return CStringArrayToXPCArray(mMimeDescriptions, aCount, aResults); +} + +NS_IMETHODIMP +nsFakePluginTag::GetExtensions(uint32_t* aCount, char16_t*** aResults) +{ + return CStringArrayToXPCArray(mExtensions, aCount, aResults); +} + +NS_IMETHODIMP +nsFakePluginTag::GetActive(bool *aResult) +{ + // Fake plugins can't be blocklisted, so this is just !Disabled + *aResult = IsEnabled(); + return NS_OK; +} + +NS_IMETHODIMP +nsFakePluginTag::GetLastModifiedTime(PRTime* aLastModifiedTime) +{ + // FIXME-jsplugins What should this return, if anything? + MOZ_ASSERT(aLastModifiedTime); + *aLastModifiedTime = 0; + return NS_OK; +} diff --git a/dom/plugins/base/nsPluginTags.h b/dom/plugins/base/nsPluginTags.h index 35e8bc7ae98..088b3a7838b 100644 --- a/dom/plugins/base/nsPluginTags.h +++ b/dom/plugins/base/nsPluginTags.h @@ -15,13 +15,80 @@ #include "nsITimer.h" #include "nsString.h" +class nsIURI; struct PRLibrary; struct nsPluginInfo; class nsNPAPIPlugin; +namespace mozilla { +namespace dom { +struct FakePluginTagInit; +} // namespace dom +} // namespace mozilla + +// An interface representing plugin tags internally. +#define NS_IINTERNALPLUGINTAG_IID \ +{ 0xe8fdd227, 0x27da, 0x46ee, \ + { 0xbe, 0xf3, 0x1a, 0xef, 0x5a, 0x8f, 0xc5, 0xb4 } } + +class nsIInternalPluginTag : public nsIPluginTag +{ +public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IINTERNALPLUGINTAG_IID) + + nsIInternalPluginTag(); + nsIInternalPluginTag(const char* aName, const char* aDescription, + const char* aFileName, const char* aVersion); + nsIInternalPluginTag(const char* aName, const char* aDescription, + const char* aFileName, const char* aVersion, + const nsTArray& aMimeTypes, + const nsTArray& aMimeDescriptions, + const nsTArray& aExtensions); + + virtual bool IsEnabled() = 0; + virtual const nsCString& GetNiceFileName() = 0; + + const nsCString& Name() const { return mName; } + const nsCString& Description() const { return mDescription; } + + const nsTArray& MimeTypes() const { return mMimeTypes; } + + const nsTArray& MimeDescriptions() const { + return mMimeDescriptions; + } + + const nsTArray& Extensions() const { return mExtensions; } + + const nsCString& FileName() const { return mFileName; } + + const nsCString& Version() const { return mVersion; } + + // Returns true if this plugin claims it supports this MIME type. The + // comparison is done ASCII-case-insensitively. + bool HasMimeType(const nsACString & aMimeType) const; + + // Returns true if this plugin claims it supports the given extension. In + // that case, aMatchingType is set to the MIME type the plugin claims + // corresponds to this extension. The match on aExtension is done + // ASCII-case-insensitively. + bool HasExtension(const nsACString & aExtension, + /* out */ nsACString & aMatchingType) const; +protected: + ~nsIInternalPluginTag(); + + nsCString mName; // UTF-8 + nsCString mDescription; // UTF-8 + nsCString mFileName; // UTF-8 + nsCString mVersion; // UTF-8 + nsTArray mMimeTypes; // UTF-8 + nsTArray mMimeDescriptions; // UTF-8 + nsTArray mExtensions; // UTF-8 +}; +NS_DEFINE_STATIC_IID_ACCESSOR(nsIInternalPluginTag, NS_IINTERNALPLUGINTAG_IID) + // A linked-list of plugin information that is used for instantiating plugins // and reflecting plugin information into JavaScript. -class nsPluginTag final : public nsIPluginTag +class nsPluginTag final : public nsIInternalPluginTag { public: NS_DECL_ISUPPORTS @@ -69,7 +136,7 @@ public: // plugin is enabled and not blocklisted bool IsActive(); - bool IsEnabled(); + bool IsEnabled() override; void SetEnabled(bool enabled); bool IsClicktoplay(); bool IsBlocklisted(); @@ -81,7 +148,7 @@ public: void ImportFlagsToPrefs(uint32_t flag); bool HasSameNameAndMimes(const nsPluginTag *aPluginTag) const; - nsCString GetNiceFileName(); + const nsCString& GetNiceFileName() override; bool IsFromExtension() const; @@ -94,32 +161,16 @@ public: // True if we've ever created an instance of this plugin in the current process. bool mHadLocalInstance; - nsCString mName; // UTF-8 - nsCString mDescription; // UTF-8 - nsTArray mMimeTypes; // UTF-8 - nsTArray mMimeDescriptions; // UTF-8 - nsTArray mExtensions; // UTF-8 PRLibrary *mLibrary; nsRefPtr mPlugin; bool mIsJavaPlugin; bool mIsFlashPlugin; - nsCString mFileName; // UTF-8 nsCString mFullPath; // UTF-8 - nsCString mVersion; // UTF-8 int64_t mLastModifiedTime; nsCOMPtr mUnloadTimer; void InvalidateBlocklistState(); - // Returns true if this plugin claims it supports this MIME type. The - // comparison is done ASCII-case-insensitively. - bool HasMimeType(const nsACString & aMimeType) const; - // Returns true if this plugin claims it supports the given extension. In hat - // case, aMatchingType is set to the MIME type the plugin claims corresponds - // to this extension. Again, the extension is done ASCII-case-insensitively. - bool HasExtension(const nsACString & aExtension, - /* out */ nsACString & aMatchingType) const; - private: virtual ~nsPluginTag(); @@ -138,4 +189,39 @@ private: static uint32_t sNextId; }; +// A class representing "fake" plugin tags; that is plugin tags not +// corresponding to actual NPAPI plugins. In practice these are all +// JS-implemented plugins; maybe we want a better name for this class? +class nsFakePluginTag : public nsIInternalPluginTag, + public nsIFakePluginTag +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPLUGINTAG + NS_DECL_NSIFAKEPLUGINTAG + + static nsresult Create(const mozilla::dom::FakePluginTagInit& aInitDictionary, + nsFakePluginTag** aPluginTag); + + bool IsEnabled() override; + const nsCString& GetNiceFileName() override; + + bool HandlerURIMatches(nsIURI* aURI); + + nsIURI* HandlerURI() const { return mHandlerURI; } + +private: + nsFakePluginTag(); + virtual ~nsFakePluginTag(); + + // The URI of the handler for our fake plugin. + // FIXME-jsplugins do we need to sanity check these? + nsCOMPtr mHandlerURI; + + nsCString mFullPath; + nsCString mNiceName; + + nsPluginTag::PluginState mState; +}; + #endif // nsPluginTags_h_ diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp index fde3ce2ee7d..996a1d2c683 100755 --- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -1341,8 +1341,8 @@ PluginModuleParent::GetPluginDetails() if (!pluginTag) { return false; } - mPluginName = pluginTag->mName; - mPluginVersion = pluginTag->mVersion; + mPluginName = pluginTag->Name(); + mPluginVersion = pluginTag->Version(); mIsFlashPlugin = pluginTag->mIsFlashPlugin; return true; } @@ -2412,7 +2412,10 @@ PluginModuleParent::DoShutdown(NPError* error) // CallNP_Shutdown() message Close(); - mShutdown = ok; + // mShutdown should either be initialized to false, or be transitiong from + // false to true. It is never ok to go from true to false. Using OR for + // the following assignment to ensure this. + mShutdown |= ok; if (!ok) { *error = NPERR_GENERIC_ERROR; } diff --git a/dom/push/Push.js b/dom/push/Push.js index 695f28cf0d6..bbf7dcf8d7f 100644 --- a/dom/push/Push.js +++ b/dom/push/Push.js @@ -15,99 +15,11 @@ function debug(s) { const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; +const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); -Cu.import("resource://gre/modules/AppsUtils.jsm"); - -const PUSH_SUBSCRIPTION_CID = Components.ID("{CA86B665-BEDA-4212-8D0F-5C9F65270B58}"); - -function PushSubscription(pushEndpoint, scope, principal) { - debug("PushSubscription Constructor"); - this._pushEndpoint = pushEndpoint; - this._scope = scope; - this._principal = principal; -} - -PushSubscription.prototype = { - __proto__: DOMRequestIpcHelper.prototype, - - contractID: "@mozilla.org/push/PushSubscription;1", - - classID : PUSH_SUBSCRIPTION_CID, - - QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer, - Ci.nsISupportsWeakReference, - Ci.nsIObserver]), - - init: function(aWindow) { - debug("PushSubscription init()"); - - this.initDOMRequestHelper(aWindow, [ - "PushService:Unregister:OK", - "PushService:Unregister:KO", - ]); - - this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"] - .getService(Ci.nsISyncMessageSender); - }, - - __init: function(endpoint, scope, principal) { - this._pushEndpoint = endpoint; - this._scope = scope; - this._principal = principal; - }, - - get endpoint() { - return this._pushEndpoint; - }, - - unsubscribe: function() { - debug("unsubscribe! ") - - let promiseInit = function(resolve, reject) { - let resolverId = this.getPromiseResolverId({resolve: resolve, - reject: reject }); - - this._cpmm.sendAsyncMessage("Push:Unregister", { - scope: this._scope, - pushEndpoint: this._pushEndpoint, - requestID: resolverId - }, null, this._principal); - }.bind(this); - - return this.createPromise(promiseInit); - }, - - receiveMessage: function(aMessage) { - debug("push subscription receiveMessage(): " + JSON.stringify(aMessage)) - - let json = aMessage.data; - let resolver = this.takePromiseResolver(json.requestID); - if (resolver == null) { - return; - } - - switch (aMessage.name) { - case "PushService:Unregister:OK": - if (typeof json.result !== "boolean") { - debug("Expected boolean result from PushService!"); - resolve.reject("NetworkError"); - return; - } - - resolver.resolve(json.result); - break; - case "PushService:Unregister:KO": - resolver.reject("NetworkError"); - break; - default: - debug("NOT IMPLEMENTED! receiveMessage for " + aMessage.name); - } - }, - -}; const PUSH_CID = Components.ID("{cde1d019-fad8-4044-b141-65fb4fb7a245}"); @@ -140,16 +52,11 @@ Push.prototype = { this._window = aWindow; - this.initDOMRequestHelper(aWindow, [ - "PushService:Register:OK", - "PushService:Register:KO", - "PushService:Registration:OK", - "PushService:Registration:KO" - ]); + this.initDOMRequestHelper(aWindow); - this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"] - .getService(Ci.nsISyncMessageSender); this._principal = aWindow.document.nodePrincipal; + + this._client = Cc["@mozilla.org/push/PushClient;1"].createInstance(Ci.nsIPushClient); }, setScope: function(scope){ @@ -199,7 +106,6 @@ Push.prototype = { window: this._window }; - debug("asking the window utils about permission...") // Using askPermission from nsIDOMWindowUtils that takes care of the // remoting if needed. let windowUtils = this._window.QueryInterface(Ci.nsIInterfaceRequestor) @@ -207,92 +113,46 @@ Push.prototype = { windowUtils.askPermission(request); }, + getEndpointResponse: function(fn) { + debug("GetEndpointResponse " + fn.toSource()); + let that = this; + let p = this.createPromise(function(resolve, reject) { + this.askPermission( + () => { + fn(that._scope, that._principal, { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIPushEndpointCallback]), + onPushEndpoint: function(ok, endpoint) { + if (ok === Cr.NS_OK) { + if (endpoint) { + let sub = new that._window.PushSubscription(endpoint, that._scope); + sub.setPrincipal(that._principal); + resolve(sub); + } else { + resolve(null); + } + } else { + reject("AbortError"); + } + } + }); + }, - - receiveMessage: function(aMessage) { - debug("push receiveMessage(): " + JSON.stringify(aMessage)) - - let json = aMessage.data; - let resolver = this.takePromiseResolver(json.requestID); - - if (!resolver) { - return; - } - - switch (aMessage.name) { - case "PushService:Register:OK": - { - let subscription = - new this._window.PushSubscription(json.pushEndpoint, this._scope, - this._principal); - resolver.resolve(subscription); - break; - } - case "PushService:Register:KO": - resolver.reject(null); - break; - case "PushService:Registration:OK": - { - let subscription = null; - try { - subscription = - new this._window.PushSubscription(json.registration.pushEndpoint, - this._scope, this._principal); - } catch(error) { + () => { + reject("PermissionDeniedError"); } - resolver.resolve(subscription); - break; - } - case "PushService:Registration:KO": - resolver.reject(null); - break; - default: - debug("NOT IMPLEMENTED! receiveMessage for " + aMessage.name); - } + ); + }.bind(this)); + return p; }, subscribe: function() { debug("subscribe()"); - let p = this.createPromise(function(resolve, reject) { - let resolverId = this.getPromiseResolverId({ resolve: resolve, reject: reject }); - - this.askPermission( - function() { - this._cpmm.sendAsyncMessage("Push:Register", { - scope: this._scope, - requestID: resolverId - }, null, this._principal); - }.bind(this), - - function() { - reject("PermissionDeniedError"); - } - ); - }.bind(this)); - return p; + return this.getEndpointResponse(this._client.subscribe.bind(this._client)); }, getSubscription: function() { debug("getSubscription()" + this._scope); - - let p = this.createPromise(function(resolve, reject) { - - let resolverId = this.getPromiseResolverId({ resolve: resolve, reject: reject }); - - this.askPermission( - function() { - this._cpmm.sendAsyncMessage("Push:Registration", { - scope: this._scope, - requestID: resolverId - }, null, this._principal); - }.bind(this), - - function() { - reject("PermissionDeniedError"); - } - ); - }.bind(this)); - return p; + return this.getEndpointResponse(this._client.getSubscription.bind(this._client)); }, permissionState: function() { @@ -324,4 +184,4 @@ Push.prototype = { }, } -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Push, PushSubscription]); +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Push]); diff --git a/dom/push/Push.manifest b/dom/push/Push.manifest index d20f13e9328..49ba27bf127 100644 --- a/dom/push/Push.manifest +++ b/dom/push/Push.manifest @@ -2,9 +2,6 @@ component {cde1d019-fad8-4044-b141-65fb4fb7a245} Push.js contract @mozilla.org/push/PushManager;1 {cde1d019-fad8-4044-b141-65fb4fb7a245} -component {CA86B665-BEDA-4212-8D0F-5C9F65270B58} Push.js -contract @mozilla.org/push/PushSubscription;1 {CA86B665-BEDA-4212-8D0F-5C9F65270B58} - # XPCOM component; initializes the PushService on startup. component {32028e38-903b-4a64-a180-5857eb4cb3dd} PushNotificationService.js contract @mozilla.org/push/NotificationService;1 {32028e38-903b-4a64-a180-5857eb4cb3dd} @@ -12,3 +9,6 @@ category app-startup PushNotificationService @mozilla.org/push/NotificationServi component {66a87970-6dc9-46e0-ac61-adb4a13791de} PushNotificationService.js contract @mozilla.org/push/ObserverNotification;1 {66a87970-6dc9-46e0-ac61-adb4a13791de} + +component {16042199-bec0-484a-9640-25ecc0c0a149} PushClient.js +contract @mozilla.org/push/PushClient;1 {16042199-bec0-484a-9640-25ecc0c0a149} diff --git a/dom/push/PushClient.js b/dom/push/PushClient.js new file mode 100644 index 00000000000..dd03380ed5a --- /dev/null +++ b/dom/push/PushClient.js @@ -0,0 +1,149 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +// Don't modify this, instead set dom.push.debug. +let gDebuggingEnabled = true; + +function debug(s) { + if (gDebuggingEnabled) + dump("-*- PushClient.js: " + s + "\n"); +} + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +const kMessages = [ + "PushService:Register:OK", + "PushService:Register:KO", + "PushService:Registration:OK", + "PushService:Registration:KO", + "PushService:Unregister:OK", + "PushService:Unregister:KO", +]; + +this.PushClient = function PushClient() { + debug("PushClient created!"); + this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"] + .getService(Ci.nsISyncMessageSender); + this._requests = {}; + this.addListeners(); +}; + +PushClient.prototype = { + classID: Components.ID("{16042199-bec0-484a-9640-25ecc0c0a149}"), + + contractID: "@mozilla.org/push/PushClient;1", + + QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, + Ci.nsIPushClient, + Ci.nsIMessageListener,]), + + + _getRandomId: function() { + return Cc["@mozilla.org/uuid-generator;1"] + .getService(Ci.nsIUUIDGenerator).generateUUID().toString(); + }, + + addRequest: function(data) { + let id = this._getRandomId(); + this._requests[id] = data; + return id; + }, + + takeRequest: function(requestId) { + let d = this._requests[requestId]; + delete this._requests[requestId]; + return d; + }, + + addListeners: function() { + for (let message of kMessages) { + this._cpmm.addWeakMessageListener(message, this); + } + }, + + subscribe: function(scope, principal, callback) { + debug("subscribe() " + scope); + let requestId = this.addRequest(callback); + this._cpmm.sendAsyncMessage("Push:Register", { + scope: scope, + requestID: requestId, + }, null, principal); + }, + + unsubscribe: function(scope, principal, callback) { + debug("unsubscribe() " + scope); + let requestId = this.addRequest(callback); + this._cpmm.sendAsyncMessage("Push:Unregister", { + scope: scope, + requestID: requestId, + }, null, principal); + }, + + getSubscription: function(scope, principal, callback) { + debug("getSubscription()" + scope); + let requestId = this.addRequest(callback); + debug("Going to send " + scope + " " + principal + " " + requestId); + this._cpmm.sendAsyncMessage("Push:Registration", { + scope: scope, + requestID: requestId, + }, null, principal); + }, + + receiveMessage: function(aMessage) { + + let json = aMessage.data; + let request = this.takeRequest(json.requestID); + + if (!request) { + return; + } + + debug("receiveMessage(): " + JSON.stringify(aMessage)) + switch (aMessage.name) { + case "PushService:Register:OK": + { + request.onPushEndpoint(Cr.NS_OK, json.pushEndpoint); + break; + } + case "PushService:Register:KO": + request.onPushEndpoint(Cr.NS_ERROR_FAILURE, ""); + break; + case "PushService:Registration:OK": + { + let endpoint = ""; + if (json.registration) + endpoint = json.registration.pushEndpoint; + request.onPushEndpoint(Cr.NS_OK, endpoint); + break; + } + case "PushService:Registration:KO": + request.onPushEndpoint(Cr.NS_ERROR_FAILURE, ""); + break; + case "PushService:Unregister:OK": + if (typeof json.result !== "boolean") { + debug("Expected boolean result from PushService!"); + request.onUnsubscribe(Cr.NS_ERROR_FAILURE, false); + return; + } + + request.onUnsubscribe(Cr.NS_OK, json.result); + break; + case "PushService:Unregister:KO": + request.onUnsubscribe(Cr.NS_ERROR_FAILURE, false); + break; + default: + debug("NOT IMPLEMENTED! receiveMessage for " + aMessage.name); + } + }, +}; + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PushClient]); diff --git a/dom/push/PushManager.cpp b/dom/push/PushManager.cpp new file mode 100644 index 00000000000..33d96b24765 --- /dev/null +++ b/dom/push/PushManager.cpp @@ -0,0 +1,839 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/PushManager.h" + +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "mozilla/dom/PushManagerBinding.h" +#include "mozilla/dom/PushSubscriptionBinding.h" +#include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h" + +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/PromiseWorkerProxy.h" + +#include "nsIGlobalObject.h" +#include "nsIPermissionManager.h" +#include "nsIPrincipal.h" +#include "nsIPushClient.h" + +#include "nsFrameMessageManager.h" +#include "nsContentCID.h" + +#include "WorkerRunnable.h" +#include "WorkerPrivate.h" +#include "WorkerScope.h" + +namespace mozilla { +namespace dom { + +using namespace workers; + +class UnsubscribeResultCallback final : public nsIUnsubscribeResultCallback +{ +public: + NS_DECL_ISUPPORTS + + explicit UnsubscribeResultCallback(Promise* aPromise) + : mPromise(aPromise) + { + AssertIsOnMainThread(); + } + + NS_IMETHOD + OnUnsubscribe(nsresult aStatus, bool aSuccess) override + { + if (NS_SUCCEEDED(aStatus)) { + mPromise->MaybeResolve(aSuccess); + } else { + mPromise->MaybeReject(NS_ERROR_DOM_NETWORK_ERR); + } + + return NS_OK; + } + +private: + ~UnsubscribeResultCallback() + {} + + nsRefPtr mPromise; +}; + +NS_IMPL_ISUPPORTS(UnsubscribeResultCallback, nsIUnsubscribeResultCallback) + +already_AddRefed +PushSubscription::Unsubscribe(ErrorResult& aRv) +{ + MOZ_ASSERT(mPrincipal); + + nsCOMPtr client = + do_CreateInstance("@mozilla.org/push/PushClient;1"); + if (NS_WARN_IF(!client)) { + aRv = NS_ERROR_FAILURE; + return nullptr; + } + + nsRefPtr p = Promise::Create(mGlobal, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + nsRefPtr callback = + new UnsubscribeResultCallback(p); + client->Unsubscribe(mScope, mPrincipal, callback); + return p.forget(); +} + +PushSubscription::PushSubscription(nsIGlobalObject* aGlobal, + const nsAString& aEndpoint, + const nsAString& aScope) + : mGlobal(aGlobal), mEndpoint(aEndpoint), mScope(aScope) +{ +} + +PushSubscription::~PushSubscription() +{} + +JSObject* +PushSubscription::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return PushSubscriptionBinding::Wrap(aCx, this, aGivenProto); +} + +void +PushSubscription::SetPrincipal(nsIPrincipal* aPrincipal) +{ + MOZ_ASSERT(!mPrincipal); + mPrincipal = aPrincipal; +} + +// static +already_AddRefed +PushSubscription::Constructor(GlobalObject& aGlobal, const nsAString& aEndpoint, const nsAString& aScope, ErrorResult& aRv) +{ + MOZ_ASSERT(!aEndpoint.IsEmpty()); + MOZ_ASSERT(!aScope.IsEmpty()); + nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports()); + nsRefPtr sub = new PushSubscription(global, aEndpoint, aScope); + return sub.forget(); +} + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PushSubscription, mGlobal, mPrincipal) +NS_IMPL_CYCLE_COLLECTING_ADDREF(PushSubscription) +NS_IMPL_CYCLE_COLLECTING_RELEASE(PushSubscription) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushSubscription) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +// PushManager +// static +bool +PushManager::Enabled(JSContext* aCx, JSObject* aObj) +{ + if (NS_IsMainThread()) { + return Preferences::GetBool("dom.push.enabled", false); + } + + // XXXnsm: As of this patch it seems like Push will be enabled before or with + // ServiceWorkers, so this seems OK for now. + ServiceWorkerGlobalScope* scope = nullptr; + nsresult rv = UnwrapObject(aObj, scope); + return NS_SUCCEEDED(rv); +} + +PushManager::PushManager(nsIGlobalObject* aGlobal, const nsAString& aScope) + : mGlobal(aGlobal), mScope(aScope) +{ + AssertIsOnMainThread(); +} + +PushManager::~PushManager() +{} + +JSObject* +PushManager::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + // XXXnsm I don't know if this is the right way to do it, but I want to assert + // that an implementation has been set before this object gets exposed to JS. + MOZ_ASSERT(mImpl); + return PushManagerBinding::Wrap(aCx, this, aGivenProto); +} + +void +PushManager::SetPushManagerImpl(PushManagerImpl& foo, ErrorResult& aRv) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mImpl); + mImpl = &foo; +} + +already_AddRefed +PushManager::Subscribe(ErrorResult& aRv) +{ + MOZ_ASSERT(mImpl); + return mImpl->Subscribe(aRv); +} + +already_AddRefed +PushManager::GetSubscription(ErrorResult& aRv) +{ + MOZ_ASSERT(mImpl); + return mImpl->GetSubscription(aRv); +} + +already_AddRefed +PushManager::PermissionState(ErrorResult& aRv) +{ + MOZ_ASSERT(mImpl); + return mImpl->PermissionState(aRv); +} + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PushManager, mGlobal, mImpl) +NS_IMPL_CYCLE_COLLECTING_ADDREF(PushManager) +NS_IMPL_CYCLE_COLLECTING_RELEASE(PushManager) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushManager) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +// WorkerPushSubscription + +WorkerPushSubscription::WorkerPushSubscription(const nsAString& aEndpoint, + const nsAString& aScope) + : mEndpoint(aEndpoint), mScope(aScope) +{ + MOZ_ASSERT(!aScope.IsEmpty()); + MOZ_ASSERT(!aEndpoint.IsEmpty()); +} + +WorkerPushSubscription::~WorkerPushSubscription() +{} + +JSObject* +WorkerPushSubscription::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return PushSubscriptionBinding_workers::Wrap(aCx, this, aGivenProto); +} + +// static +already_AddRefed +WorkerPushSubscription::Constructor(GlobalObject& aGlobal, const nsAString& aEndpoint, const nsAString& aScope, ErrorResult& aRv) +{ + WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(worker); + worker->AssertIsOnWorkerThread(); + + nsRefPtr sub = new WorkerPushSubscription(aEndpoint, aScope); + return sub.forget(); +} + +class MOZ_STACK_CLASS AutoReleasePromiseWorkerProxy final +{ +public: + explicit AutoReleasePromiseWorkerProxy(PromiseWorkerProxy* aProxy) + : mProxy(aProxy) + { + AssertIsOnMainThread(); + MOZ_ASSERT(aProxy); + aProxy->GetCleanUpLock().AssertCurrentThreadOwns(); + if (aProxy->IsClean()) { + mProxy = nullptr; + } + } + + ~AutoReleasePromiseWorkerProxy() + { + if (mProxy) { + AutoJSAPI jsapi; + jsapi.Init(); + + nsRefPtr cr = + new PromiseWorkerProxyControlRunnable(mProxy->GetWorkerPrivate(), + mProxy); + + DebugOnly ok = cr->Dispatch(jsapi.cx()); + MOZ_ASSERT(ok); + mProxy = nullptr; + } + } +private: + nsRefPtr mProxy; +}; + +class UnsubscribeResultRunnable final : public WorkerRunnable +{ +public: + UnsubscribeResultRunnable(PromiseWorkerProxy* aProxy, + nsresult aStatus, + bool aSuccess) + : WorkerRunnable(aProxy->GetWorkerPrivate(), WorkerThreadModifyBusyCount) + , mProxy(aProxy) + , mStatus(aStatus) + , mSuccess(aSuccess) + { + AssertIsOnMainThread(); + } + + bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override + { + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + + nsRefPtr proxy = mProxy.forget(); + nsRefPtr promise = proxy->GetWorkerPromise(); + if (NS_SUCCEEDED(mStatus)) { + promise->MaybeResolve(mSuccess); + } else { + promise->MaybeReject(NS_ERROR_DOM_NETWORK_ERR); + } + + proxy->CleanUp(aCx); + return true; + } +private: + ~UnsubscribeResultRunnable() + { + if (mProxy) { + AutoReleasePromiseWorkerProxy autoRelease(mProxy); + mProxy = nullptr; + } + } + + nsRefPtr mProxy; + nsresult mStatus; + bool mSuccess; +}; + +class WorkerUnsubscribeResultCallback final : public nsIUnsubscribeResultCallback +{ +public: + NS_DECL_ISUPPORTS + + explicit WorkerUnsubscribeResultCallback(PromiseWorkerProxy* aProxy) + : mProxy(aProxy) + { + AssertIsOnMainThread(); + } + + NS_IMETHOD + OnUnsubscribe(nsresult aStatus, bool aSuccess) override + { + AssertIsOnMainThread(); + if (!mProxy) { + return NS_OK; + } + + MutexAutoLock lock(mProxy->GetCleanUpLock()); + if (mProxy->IsClean()) { + return NS_OK; + } + + AutoJSAPI jsapi; + jsapi.Init(); + + nsRefPtr r = + new UnsubscribeResultRunnable(mProxy, aStatus, aSuccess); + mProxy = nullptr; + + r->Dispatch(jsapi.cx()); + return NS_OK; + } + +private: + ~WorkerUnsubscribeResultCallback() + { + if (mProxy) { + AutoReleasePromiseWorkerProxy autoRelease(mProxy); + mProxy = nullptr; + } + } + + nsRefPtr mProxy; +}; + +NS_IMPL_ISUPPORTS(WorkerUnsubscribeResultCallback, nsIUnsubscribeResultCallback) + +class UnsubscribeRunnable final : public nsRunnable +{ +public: + UnsubscribeRunnable(PromiseWorkerProxy* aProxy, + const nsAString& aScope) + : mProxy(aProxy) + , mScope(aScope) + { + MOZ_ASSERT(aProxy); + MOZ_ASSERT(!aScope.IsEmpty()); + } + + NS_IMETHOD + Run() override + { + AssertIsOnMainThread(); + MutexAutoLock lock(mProxy->GetCleanUpLock()); + if (mProxy->IsClean()) { + return NS_OK; + } + + nsCOMPtr client = + do_CreateInstance("@mozilla.org/push/PushClient;1"); + if (!client) { + AutoJSAPI jsapi; + jsapi.Init(); + + nsRefPtr r = + new UnsubscribeResultRunnable(mProxy, NS_ERROR_FAILURE, false); + mProxy = nullptr; + + r->Dispatch(jsapi.cx()); + return NS_OK; + } + + nsCOMPtr principal = mProxy->GetWorkerPrivate()->GetPrincipal(); + nsRefPtr callback = + new WorkerUnsubscribeResultCallback(mProxy); + mProxy = nullptr; + client->Unsubscribe(mScope, principal, callback); + return NS_OK; + } + +private: + ~UnsubscribeRunnable() + { + if (mProxy) { + AutoReleasePromiseWorkerProxy autoRelease(mProxy); + mProxy = nullptr; + } + } + nsRefPtr mProxy; + nsString mScope; +}; + +already_AddRefed +WorkerPushSubscription::Unsubscribe(ErrorResult &aRv) +{ + WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(worker); + worker->AssertIsOnWorkerThread(); + + nsCOMPtr global = worker->GlobalScope(); + nsRefPtr p = Promise::Create(global, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + nsRefPtr proxy = PromiseWorkerProxy::Create(worker, p); + if (!proxy) { + p->MaybeReject(NS_ERROR_DOM_NETWORK_ERR); + return p.forget(); + } + + nsRefPtr r = + new UnsubscribeRunnable(proxy, mScope); + NS_DispatchToMainThread(r); + + return p.forget(); +} + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WorkerPushSubscription) +NS_IMPL_CYCLE_COLLECTING_ADDREF(WorkerPushSubscription) +NS_IMPL_CYCLE_COLLECTING_RELEASE(WorkerPushSubscription) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerPushSubscription) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +// WorkerPushManager + +WorkerPushManager::WorkerPushManager(const nsAString& aScope) + : mScope(aScope) +{ +} + +JSObject* +WorkerPushManager::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return PushManagerBinding_workers::Wrap(aCx, this, aGivenProto); +} + +class GetSubscriptionResultRunnable final : public WorkerRunnable +{ +public: + GetSubscriptionResultRunnable(PromiseWorkerProxy* aProxy, + nsresult aStatus, + const nsAString& aEndpoint, + const nsAString& aScope) + : WorkerRunnable(aProxy->GetWorkerPrivate(), WorkerThreadModifyBusyCount) + , mProxy(aProxy) + , mStatus(aStatus) + , mEndpoint(aEndpoint) + , mScope(aScope) + { } + + bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override + { + nsRefPtr proxy = mProxy.forget(); + nsRefPtr promise = proxy->GetWorkerPromise(); + if (NS_SUCCEEDED(mStatus)) { + nsRefPtr sub = + new WorkerPushSubscription(mEndpoint, mScope); + promise->MaybeResolve(sub); + } else { + promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + } + + proxy->CleanUp(aCx); + return true; + } +private: + ~GetSubscriptionResultRunnable() + { + if (mProxy) { + AutoReleasePromiseWorkerProxy autoRelease(mProxy); + mProxy = nullptr; + } + } + + nsRefPtr mProxy; + nsresult mStatus; + nsString mEndpoint; + nsString mScope; +}; + +class GetSubscriptionCallback final : public nsIPushEndpointCallback +{ +public: + NS_DECL_ISUPPORTS + + explicit GetSubscriptionCallback(PromiseWorkerProxy* aProxy, + const nsAString& aScope) + : mProxy(aProxy) + , mScope(aScope) + {} + + NS_IMETHOD + OnPushEndpoint(nsresult aStatus, const nsAString& aEndpoint) override + { + AssertIsOnMainThread(); + if (!mProxy) { + return NS_OK; + } + + MutexAutoLock lock(mProxy->GetCleanUpLock()); + if (mProxy->IsClean()) { + return NS_OK; + } + + AutoJSAPI jsapi; + jsapi.Init(); + + nsRefPtr r = + new GetSubscriptionResultRunnable(mProxy, aStatus, aEndpoint, mScope); + mProxy = nullptr; + + r->Dispatch(jsapi.cx()); + return NS_OK; + } + +protected: + ~GetSubscriptionCallback() + { + if (mProxy) { + AutoReleasePromiseWorkerProxy autoRelease(mProxy); + mProxy = nullptr; + } + } + +private: + nsRefPtr mProxy; + nsString mScope; +}; + +NS_IMPL_ISUPPORTS(GetSubscriptionCallback, nsIPushEndpointCallback) + +class GetSubscriptionRunnable final : public nsRunnable +{ +public: + GetSubscriptionRunnable(PromiseWorkerProxy* aProxy, + const nsAString& aScope, + WorkerPushManager::SubscriptionAction aAction) + : mProxy(aProxy) + , mScope(aScope), mAction(aAction) + {} + + NS_IMETHOD + Run() override + { + AssertIsOnMainThread(); + MutexAutoLock lock(mProxy->GetCleanUpLock()); + if (mProxy->IsClean()) { + return NS_OK; + } + + nsCOMPtr permManager = + mozilla::services::GetPermissionManager(); + + AutoJSAPI jsapi; + jsapi.Init(); + + if (!permManager) { + Fail(jsapi.cx()); + return NS_OK; + } + + uint32_t permission = nsIPermissionManager::DENY_ACTION; + nsresult rv = permManager->TestExactPermissionFromPrincipal( + mProxy->GetWorkerPrivate()->GetPrincipal(), + "push", + &permission); + + if (NS_WARN_IF(NS_FAILED(rv)) || permission != nsIPermissionManager::ALLOW_ACTION) { + Fail(jsapi.cx()); + return NS_OK; + } + + nsCOMPtr client = + do_CreateInstance("@mozilla.org/push/PushClient;1"); + if (!client) { + Fail(jsapi.cx()); + return NS_OK; + } + + nsCOMPtr principal = mProxy->GetWorkerPrivate()->GetPrincipal(); + nsRefPtr callback = new GetSubscriptionCallback(mProxy, mScope); + mProxy = nullptr; + + if (mAction == WorkerPushManager::SubscribeAction) { + return client->Subscribe(mScope, principal, callback); + } else { + MOZ_ASSERT(mAction == WorkerPushManager::GetSubscriptionAction); + return client->GetSubscription(mScope, principal, callback); + } + } + +private: + void + Fail(JSContext* aCx) + { + nsRefPtr r = + new GetSubscriptionResultRunnable(mProxy, NS_ERROR_FAILURE, EmptyString(), mScope); + mProxy = nullptr; + + r->Dispatch(aCx); + } + + ~GetSubscriptionRunnable() + { + if (mProxy) { + AutoReleasePromiseWorkerProxy autoRelease(mProxy); + mProxy = nullptr; + } + } + + nsRefPtr mProxy; + nsString mScope; + WorkerPushManager::SubscriptionAction mAction; +}; + +already_AddRefed +WorkerPushManager::PerformSubscriptionAction(SubscriptionAction aAction, ErrorResult& aRv) +{ + WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(worker); + worker->AssertIsOnWorkerThread(); + + nsCOMPtr global = worker->GlobalScope(); + nsRefPtr p = Promise::Create(global, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + nsRefPtr proxy = PromiseWorkerProxy::Create(worker, p); + if (!proxy) { + p->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + return p.forget(); + } + + nsRefPtr r = + new GetSubscriptionRunnable(proxy, mScope, aAction); + NS_DispatchToMainThread(r); + + return p.forget(); +} + +already_AddRefed +WorkerPushManager::Subscribe(ErrorResult& aRv) +{ + return PerformSubscriptionAction(SubscribeAction, aRv); +} + +already_AddRefed +WorkerPushManager::GetSubscription(ErrorResult& aRv) +{ + return PerformSubscriptionAction(GetSubscriptionAction, aRv); +} + +class PermissionResultRunnable final : public WorkerRunnable +{ +public: + PermissionResultRunnable(PromiseWorkerProxy *aProxy, + nsresult aStatus, + PushPermissionState aState) + : WorkerRunnable(aProxy->GetWorkerPrivate(), WorkerThreadModifyBusyCount) + , mProxy(aProxy) + , mStatus(aStatus) + , mState(aState) + { + AssertIsOnMainThread(); + } + + bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override + { + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + + nsRefPtr proxy = mProxy.forget(); + nsRefPtr promise = proxy->GetWorkerPromise(); + if (NS_SUCCEEDED(mStatus)) { + MOZ_ASSERT(uint32_t(mState) < ArrayLength(PushPermissionStateValues::strings)); + nsAutoCString stringState(PushPermissionStateValues::strings[uint32_t(mState)].value, PushPermissionStateValues::strings[uint32_t(mState)].length); + promise->MaybeResolve(NS_ConvertUTF8toUTF16(stringState)); + } else { + promise->MaybeReject(aCx, JS::UndefinedHandleValue); + } + + proxy->CleanUp(aCx); + return true; + } + +private: + ~PermissionResultRunnable() + { + if (mProxy) { + AutoReleasePromiseWorkerProxy autoRelease(mProxy); + mProxy = nullptr; + } + } + + nsRefPtr mProxy; + nsresult mStatus; + PushPermissionState mState; +}; + +class PermissionStateRunnable final : public nsRunnable +{ +public: + explicit PermissionStateRunnable(PromiseWorkerProxy* aProxy) + : mProxy(aProxy) + {} + + NS_IMETHOD + Run() override + { + AssertIsOnMainThread(); + MutexAutoLock lock(mProxy->GetCleanUpLock()); + if (mProxy->IsClean()) { + return NS_OK; + } + + nsCOMPtr permManager = + mozilla::services::GetPermissionManager(); + + PushPermissionState state = PushPermissionState::Denied; + + AutoJSAPI jsapi; + jsapi.Init(); + + if (!permManager) { + nsRefPtr r = + new PermissionResultRunnable(mProxy, NS_ERROR_FAILURE, state); + mProxy = nullptr; + + r->Dispatch(jsapi.cx()); + return NS_OK; + } + + uint32_t permission = nsIPermissionManager::DENY_ACTION; + nsresult rv = permManager->TestExactPermissionFromPrincipal( + mProxy->GetWorkerPrivate()->GetPrincipal(), + "push", + &permission); + + switch (permission) { + case nsIPermissionManager::ALLOW_ACTION: + state = PushPermissionState::Granted; + break; + case nsIPermissionManager::DENY_ACTION: + state = PushPermissionState::Denied; + break; + case nsIPermissionManager::PROMPT_ACTION: + state = PushPermissionState::Prompt; + break; + default: + MOZ_CRASH("Unexpected case!"); + } + + nsRefPtr r = + new PermissionResultRunnable(mProxy, rv, state); + mProxy = nullptr; + r->Dispatch(jsapi.cx()); + return NS_OK; + } + +private: + ~PermissionStateRunnable() + { + if (mProxy) { + AutoReleasePromiseWorkerProxy autoRelease(mProxy); + mProxy = nullptr; + } + } + + nsRefPtr mProxy; +}; + +already_AddRefed +WorkerPushManager::PermissionState(ErrorResult& aRv) +{ + WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(worker); + worker->AssertIsOnWorkerThread(); + + nsCOMPtr global = worker->GlobalScope(); + nsRefPtr p = Promise::Create(global, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + nsRefPtr proxy = PromiseWorkerProxy::Create(worker, p); + if (!proxy) { + p->MaybeReject(worker->GetJSContext(), JS::UndefinedHandleValue); + return p.forget(); + } + + nsRefPtr r = + new PermissionStateRunnable(proxy); + NS_DispatchToMainThread(r); + + return p.forget(); +} + +WorkerPushManager::~WorkerPushManager() +{} + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WorkerPushManager) +NS_IMPL_CYCLE_COLLECTING_ADDREF(WorkerPushManager) +NS_IMPL_CYCLE_COLLECTING_RELEASE(WorkerPushManager) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WorkerPushManager) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END +} // namespace dom +} // namespace mozilla diff --git a/dom/push/PushManager.h b/dom/push/PushManager.h new file mode 100644 index 00000000000..5e92314aef9 --- /dev/null +++ b/dom/push/PushManager.h @@ -0,0 +1,227 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +/** + * We would like to expose PushManager and PushSubscription on window and + * workers. Parts of the Push API is implemented in JS out of necessity due to: + * 1) Using frame message managers, in which + * nsIMessageListener::receiveMessage() must be in JS. + * 2) It is easier to use certain APIs like the permission prompt and Promises + * from JS. + * + * Unfortunately, JS-implemented WebIDL is not supported off the main thread. To + * aid in fixing this, the nsIPushClient is introduced which deals with part (1) + * above. Part (2) is handled by PushManagerImpl on the main thread. PushManager + * wraps this in C++ since our bindings code cannot accomodate "JS-implemented + * on the main thread, C++ on the worker" bindings. PushManager simply forwards + * the calls to the JS component. + * + * On the worker threads, we don't have to deal with permission prompts, instead + * we just reject calls if the principal does not have permission. On workers + * WorkerPushManager dispatches runnables to the main thread which directly call + * nsIPushClient. + * + * PushSubscription is in C++ on both threads since it isn't particularly + * verbose to implement in C++ compared to JS. + */ + +#ifndef mozilla_dom_PushManager_h +#define mozilla_dom_PushManager_h + +#include "nsWrapperCache.h" + +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/dom/BindingDeclarations.h" + +#include "nsCOMPtr.h" +#include "nsRefPtr.h" +#include "jsapi.h" + +class nsIGlobalObject; +class nsIPrincipal; + +namespace mozilla { +namespace dom { + +namespace workers { +class WorkerPrivate; +} + +class Promise; +class PushManagerImpl; + +class PushSubscription final : public nsISupports + , public nsWrapperCache +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PushSubscription) + + explicit PushSubscription(nsIGlobalObject* aGlobal, + const nsAString& aEndpoint, + const nsAString& aScope); + + JSObject* + WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + nsIGlobalObject* + GetParentObject() const + { + return mGlobal; + } + + void + GetEndpoint(nsAString& aEndpoint) const + { + aEndpoint = mEndpoint; + } + + static already_AddRefed + Constructor(GlobalObject& aGlobal, const nsAString& aEndpoint, const nsAString& aScope, ErrorResult& aRv); + + void + SetPrincipal(nsIPrincipal* aPrincipal); + + already_AddRefed + Unsubscribe(ErrorResult& aRv); + +protected: + ~PushSubscription(); + +private: + nsCOMPtr mGlobal; + nsCOMPtr mPrincipal; + nsString mEndpoint; + nsString mScope; +}; + +class PushManager final : public nsISupports + , public nsWrapperCache +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PushManager) + + static bool + Enabled(JSContext* aCx, JSObject* aObj); + + explicit PushManager(nsIGlobalObject* aGlobal, const nsAString& aScope); + + nsIGlobalObject* + GetParentObject() const + { + return mGlobal; + } + + JSObject* + WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + already_AddRefed + Subscribe(ErrorResult& aRv); + + already_AddRefed + GetSubscription(ErrorResult& aRv); + + already_AddRefed + PermissionState(ErrorResult& aRv); + + void + SetPushManagerImpl(PushManagerImpl& foo, ErrorResult& aRv); + +protected: + ~PushManager(); + +private: + nsCOMPtr mGlobal; + nsRefPtr mImpl; + nsString mScope; +}; + +class WorkerPushSubscription final : public nsISupports + , public nsWrapperCache +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WorkerPushSubscription) + + explicit WorkerPushSubscription(const nsAString& aEndpoint, + const nsAString& aScope); + + nsIGlobalObject* + GetParentObject() const + { + return nullptr; + } + + JSObject* + WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + static already_AddRefed + Constructor(GlobalObject& aGlobal, const nsAString& aEndpoint, const nsAString& aScope, ErrorResult& aRv); + + void + GetEndpoint(nsAString& aEndpoint) const + { + aEndpoint = mEndpoint; + } + + already_AddRefed + Unsubscribe(ErrorResult& aRv); + +protected: + ~WorkerPushSubscription(); + +private: + nsString mEndpoint; + nsString mScope; +}; + +class WorkerPushManager final : public nsISupports + , public nsWrapperCache +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WorkerPushManager) + + enum SubscriptionAction { + SubscribeAction, + GetSubscriptionAction, + }; + + explicit WorkerPushManager(const nsAString& aScope); + + nsIGlobalObject* + GetParentObject() const + { + return nullptr; + } + + JSObject* + WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + already_AddRefed + PerformSubscriptionAction(SubscriptionAction aAction, ErrorResult& aRv); + + already_AddRefed + Subscribe(ErrorResult& aRv); + + already_AddRefed + GetSubscription(ErrorResult& aRv); + + already_AddRefed + PermissionState(ErrorResult& aRv); + +protected: + ~WorkerPushManager(); + +private: + nsString mScope; +}; +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_PushManager_h diff --git a/dom/push/PushService.jsm b/dom/push/PushService.jsm index 37198d7d632..88ba57a7d2f 100644 --- a/dom/push/PushService.jsm +++ b/dom/push/PushService.jsm @@ -406,12 +406,6 @@ this.PushService = { this._setState(PUSH_SERVICE_ACTIVATING); - var globalMM = Cc["@mozilla.org/globalmessagemanager;1"] - .getService(Ci.nsIFrameScriptLoader); - - globalMM.loadFrameScript("chrome://global/content/PushServiceChildPreload.js", - true); - // Debugging prefs.observe("debug", this); @@ -662,8 +656,6 @@ this.PushService = { }, _notifySubscriptionChangeObservers: function(record) { - let globalMM = Cc['@mozilla.org/globalmessagemanager;1'] - .getService(Ci.nsIMessageListenerManager); // Notify XPCOM observers. Services.obs.notifyObservers( null, @@ -676,7 +668,9 @@ this.PushService = { scope: record.scope }; - globalMM.broadcastAsyncMessage('pushsubscriptionchange', data); + let ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1'] + .getService(Ci.nsIMessageListenerManager); + ppmm.broadcastAsyncMessage('pushsubscriptionchange', data); }, // Fires a push-register system message to all applications that have @@ -804,9 +798,9 @@ this.PushService = { scope: aPushRecord.scope }; - let globalMM = Cc['@mozilla.org/globalmessagemanager;1'] + let ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1'] .getService(Ci.nsIMessageListenerManager); - globalMM.broadcastAsyncMessage('push', data); + ppmm.broadcastAsyncMessage('push', data); }, getByKeyID: function(aKeyID) { diff --git a/dom/push/PushServiceChildPreload.js b/dom/push/PushServiceChildPreload.jsm similarity index 71% rename from dom/push/PushServiceChildPreload.js rename to dom/push/PushServiceChildPreload.jsm index 395b1798b6f..4a81b575851 100644 --- a/dom/push/PushServiceChildPreload.js +++ b/dom/push/PushServiceChildPreload.jsm @@ -4,17 +4,22 @@ "use strict"; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + XPCOMUtils.defineLazyServiceGetter(this, "swm", "@mozilla.org/serviceworkers/manager;1", "nsIServiceWorkerManager"); -addMessageListener("push", function (aMessage) { +Services.cpmm.addMessageListener("push", function (aMessage) { swm.sendPushEvent(aMessage.data.originAttributes, aMessage.data.scope, aMessage.data.payload); }); -addMessageListener("pushsubscriptionchange", function (aMessage) { +Services.cpmm.addMessageListener("pushsubscriptionchange", function (aMessage) { swm.sendPushSubscriptionChangeEvent(aMessage.data.originAttributes, aMessage.data.scope); }); diff --git a/dom/push/moz.build b/dom/push/moz.build index 9a0bfe74b0d..8c9fcabc52c 100644 --- a/dom/push/moz.build +++ b/dom/push/moz.build @@ -6,6 +6,7 @@ EXTRA_COMPONENTS += [ 'Push.js', 'Push.manifest', + 'PushClient.js', 'PushNotificationService.js', ] @@ -17,6 +18,7 @@ EXTRA_JS_MODULES += [ 'PushDB.jsm', 'PushRecord.jsm', 'PushService.jsm', + 'PushServiceChildPreload.jsm', 'PushServiceHttp2.jsm', ] @@ -27,3 +29,17 @@ MOCHITEST_MANIFESTS += [ XPCSHELL_TESTS_MANIFESTS += [ 'test/xpcshell/xpcshell.ini', ] + +EXPORTS.mozilla.dom += [ + 'PushManager.h', +] + +UNIFIED_SOURCES += [ + 'PushManager.cpp', +] + +LOCAL_INCLUDES += [ + '../workers', +] + +FINAL_LIBRARY = 'xul' diff --git a/dom/quota/QuotaManager.cpp b/dom/quota/QuotaManager.cpp index b8c4ef273f2..3098708132e 100644 --- a/dom/quota/QuotaManager.cpp +++ b/dom/quota/QuotaManager.cpp @@ -5240,7 +5240,37 @@ StorageDirectoryHelper::ProcessOriginDirectories(bool aMove) } } - rv = originProps.mDirectory->MoveTo(permanentStorageDir, EmptyString()); + nsString leafName; + rv = originProps.mDirectory->GetLeafName(leafName); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsCOMPtr newDirectory; + rv = permanentStorageDir->Clone(getter_AddRefs(newDirectory)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = newDirectory->Append(leafName); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + bool exists; + rv = newDirectory->Exists(&exists); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (exists) { + QM_WARNING("Found %s in storage/persistent and storage/permanent !", + NS_ConvertUTF16toUTF8(leafName).get()); + + rv = originProps.mDirectory->Remove(/* recursive */ true); + } else { + rv = originProps.mDirectory->MoveTo(permanentStorageDir, EmptyString()); + } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 85dd05ce714..c6ea0563fd7 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -115,7 +115,7 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) { nsContentPolicyType contentPolicyType = aLoadInfo->GetContentPolicyType(); nsCString mimeTypeGuess; - nsCOMPtr requestingContext = nullptr; + nsCOMPtr requestingContext = nullptr; switch(contentPolicyType) { case nsIContentPolicy::TYPE_OTHER: @@ -132,30 +132,37 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo) // alias nsIContentPolicy::TYPE_DATAREQUEST: case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: case nsIContentPolicy::TYPE_DTD: - case nsIContentPolicy::TYPE_FONT: + case nsIContentPolicy::TYPE_FONT: { MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; + } - case nsIContentPolicy::TYPE_MEDIA: - mimeTypeGuess = EmptyCString(); - requestingContext = aLoadInfo->LoadingNode(); -#ifdef DEBUG - { - nsCOMPtr element = do_QueryInterface(requestingContext); - NS_ASSERTION(element != nullptr, - "type_media requires requestingContext of type Element"); + case nsIContentPolicy::TYPE_MEDIA: { + nsContentPolicyType internalContentPolicyType = + aLoadInfo->InternalContentPolicyType(); + + if (internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_TRACK) { + mimeTypeGuess = NS_LITERAL_CSTRING("text/vtt"); } -#endif + else { + mimeTypeGuess = EmptyCString(); + } + requestingContext = aLoadInfo->LoadingNode(); + MOZ_ASSERT(!requestingContext || + requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE, + "type_media requires requestingContext of type Element"); break; + } case nsIContentPolicy::TYPE_WEBSOCKET: case nsIContentPolicy::TYPE_CSP_REPORT: case nsIContentPolicy::TYPE_XSLT: case nsIContentPolicy::TYPE_BEACON: case nsIContentPolicy::TYPE_FETCH: - case nsIContentPolicy::TYPE_IMAGESET: + case nsIContentPolicy::TYPE_IMAGESET: { MOZ_ASSERT(false, "contentPolicyType not supported yet"); break; + } default: // nsIContentPolicy::TYPE_INVALID diff --git a/dom/system/NetworkGeolocationProvider.js b/dom/system/NetworkGeolocationProvider.js index 190b9fb41c0..a594cea8438 100644 --- a/dom/system/NetworkGeolocationProvider.js +++ b/dom/system/NetworkGeolocationProvider.js @@ -444,7 +444,7 @@ WifiGeoPositionProvider.prototype = { break; // CDMA cases to be handled in bug 1010282 }; - result.push({ radio: radioTechFamily, + result.push({ radioType: radioTechFamily, mobileCountryCode: voice.network.mcc, mobileNetworkCode: voice.network.mnc, locationAreaCode: cell.gsmLocationAreaCode, diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index 569dd83165e..f44709a3f72 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -923,6 +923,8 @@ var interfaceNamesInGlobalScope = "PropertyNodeList", // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PushManager", b2g: false, android: false, release: false}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "PushSubscription", b2g: false, android: false, release: false}, // IMPORTANT: Do not change this list without review from a DOM peer! "RadioNodeList", // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/webidl/BroadcastChannel.webidl b/dom/webidl/BroadcastChannel.webidl index 37c531d4a70..70be23522f2 100644 --- a/dom/webidl/BroadcastChannel.webidl +++ b/dom/webidl/BroadcastChannel.webidl @@ -8,8 +8,7 @@ */ [Constructor(DOMString channel), - Exposed=(Window,Worker), - Func="BroadcastChannel::IsEnabled"] + Exposed=(Window,Worker)] interface BroadcastChannel : EventTarget { readonly attribute DOMString name; diff --git a/dom/webidl/FakePluginTagInit.webidl b/dom/webidl/FakePluginTagInit.webidl new file mode 100644 index 00000000000..93cbad7f842 --- /dev/null +++ b/dom/webidl/FakePluginTagInit.webidl @@ -0,0 +1,39 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 http://mozilla.org/MPL/2.0/. + */ + +/** + * A fake plugin is fundamentally identified by its handlerURI. + * + * In addition to that, a fake plugin registration needs to provide at least one + * FakePluginMimeEntry so we'll know what types(s) the plugin is registered for. + * Other information is optional, though having usable niceName is highly + * recommended. + */ +dictionary FakePluginTagInit { + required DOMString handlerURI; + required sequence mimeEntries; + + // The niceName should really be provided, and be unique, if possible; it can + // be used as a key to persist state for this plug-in. + DOMString niceName = ""; + + // Other things can be provided but don't really matter that much. + DOMString fullPath = ""; + DOMString name = ""; + DOMString description = ""; + DOMString fileName = ""; + DOMString version = ""; +}; + +/** + * A single MIME entry for the fake plugin. + */ +dictionary FakePluginMimeEntry { + required DOMString type; + DOMString description = ""; + DOMString extension = ""; +}; + diff --git a/dom/webidl/PushManager.webidl b/dom/webidl/PushManager.webidl index 26420d7bf5f..a1ae9d4fdf3 100644 --- a/dom/webidl/PushManager.webidl +++ b/dom/webidl/PushManager.webidl @@ -7,9 +7,11 @@ * https://w3c.github.io/push-api/ */ +// Please see comments in dom/push/PushManager.h for the split between +// PushManagerImpl and PushManager. [JSImplementation="@mozilla.org/push/PushManager;1", - Pref="dom.push.enabled"] -interface PushManager { + NoInterfaceObject] +interface PushManagerImpl { Promise subscribe(); Promise getSubscription(); Promise permissionState(); @@ -20,6 +22,19 @@ interface PushManager { [Func="ServiceWorkerRegistration::WebPushMethodHider"] void setScope(DOMString scope); }; +[Exposed=(Window,Worker), Func="mozilla::dom::PushManager::Enabled"] +interface PushManager { + [ChromeOnly, Throws, Exposed=Window] + void setPushManagerImpl(PushManagerImpl store); + + [Throws] + Promise subscribe(); + [Throws] + Promise getSubscription(); + [Throws] + Promise permissionState(); +}; + enum PushPermissionState { "granted", diff --git a/dom/webidl/PushSubscription.webidl b/dom/webidl/PushSubscription.webidl index d97acd2cd86..37b7776234e 100644 --- a/dom/webidl/PushSubscription.webidl +++ b/dom/webidl/PushSubscription.webidl @@ -9,11 +9,16 @@ interface Principal; -[JSImplementation="@mozilla.org/push/PushSubscription;1", - Constructor(DOMString pushEndpoint, DOMString scope, Principal principal), ChromeOnly] +[Exposed=(Window,Worker), Func="mozilla::dom::PushManager::Enabled", + ChromeConstructor(DOMString pushEndpoint, DOMString scope)] interface PushSubscription { readonly attribute USVString endpoint; + [Throws] Promise unsubscribe(); jsonifier; + + // Used to set the principal from the JS implemented PushManager. + [Exposed=Window,ChromeOnly] + void setPrincipal(Principal principal); }; diff --git a/dom/webidl/ServiceWorkerRegistration.webidl b/dom/webidl/ServiceWorkerRegistration.webidl index bbf357440cc..2f220a8eaaa 100644 --- a/dom/webidl/ServiceWorkerRegistration.webidl +++ b/dom/webidl/ServiceWorkerRegistration.webidl @@ -28,7 +28,7 @@ interface ServiceWorkerRegistration : EventTarget { partial interface ServiceWorkerRegistration { #ifndef MOZ_SIMPLEPUSH - [Throws, Exposed=Window, Pref="dom.push.enabled"] + [Throws, Exposed=(Window,Worker), Func="mozilla::dom::PushManager::Enabled"] readonly attribute PushManager pushManager; #endif }; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index fc340e7946b..d17be17f422 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -146,6 +146,7 @@ WEBIDL_FILES = [ 'EventSource.webidl', 'EventTarget.webidl', 'ExtendableEvent.webidl', + 'FakePluginTagInit.webidl', 'Fetch.webidl', 'FetchEvent.webidl', 'File.webidl', diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 2c0b01c7f63..849074fc411 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -2252,7 +2252,7 @@ ServiceWorkerManager::SendPushEvent(const nsACString& aOriginAttributes, nsRefPtr serviceWorker = CreateServiceWorkerForScope(attrs, aScope, nullptr /* failure runnable */); - if (!serviceWorker) { + if (NS_WARN_IF(!serviceWorker)) { return NS_ERROR_FAILURE; } diff --git a/dom/workers/ServiceWorkerRegistration.cpp b/dom/workers/ServiceWorkerRegistration.cpp index 07f943c3529..afb74a6603a 100644 --- a/dom/workers/ServiceWorkerRegistration.cpp +++ b/dom/workers/ServiceWorkerRegistration.cpp @@ -29,6 +29,7 @@ #ifndef MOZ_SIMPLEPUSH #include "mozilla/dom/PushManagerBinding.h" +#include "mozilla/dom/PushManager.h" #endif using namespace mozilla::dom::workers; @@ -677,9 +678,15 @@ ServiceWorkerRegistrationMainThread::GetPushManager(ErrorResult& aRv) if (aRv.Failed()) { return nullptr; } - mPushManager = new PushManager(jsImplObj, globalObject); + mPushManager = new PushManager(globalObject, mScope); - mPushManager->SetScope(mScope, aRv); + nsRefPtr impl = new PushManagerImpl(jsImplObj, globalObject); + impl->SetScope(mScope, aRv); + if (aRv.Failed()) { + mPushManager = nullptr; + return nullptr; + } + mPushManager->SetPushManagerImpl(*impl, aRv); if (aRv.Failed()) { mPushManager = nullptr; return nullptr; @@ -807,10 +814,16 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(ServiceWorkerRegistrationWorkerThread) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServiceWorkerRegistrationWorkerThread, ServiceWorkerRegistrationBase) +#ifndef MOZ_SIMPLEPUSH + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPushManager) +#endif NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServiceWorkerRegistrationWorkerThread, ServiceWorkerRegistrationBase) +#ifndef MOZ_SIMPLEPUSH + NS_IMPL_CYCLE_COLLECTION_UNLINK(mPushManager) +#endif tmp->ReleaseListener(RegistrationIsGoingAway); NS_IMPL_CYCLE_COLLECTION_UNLINK_END @@ -1075,5 +1088,22 @@ ServiceWorkerRegistrationWorkerThread::GetNotifications(const GetNotificationOpt return Notification::WorkerGet(mWorkerPrivate, aOptions, mScope, aRv); } +already_AddRefed +ServiceWorkerRegistrationWorkerThread::GetPushManager(ErrorResult& aRv) +{ +#ifdef MOZ_SIMPLEPUSH + return nullptr; +#else + + if (!mPushManager) { + mPushManager = new WorkerPushManager(mScope); + } + + nsRefPtr ret = mPushManager; + return ret.forget(); + + #endif /* ! MOZ_SIMPLEPUSH */ +} + } // dom namespace } // mozilla namespace diff --git a/dom/workers/ServiceWorkerRegistration.h b/dom/workers/ServiceWorkerRegistration.h index b696b3d3dc4..72abe132e04 100644 --- a/dom/workers/ServiceWorkerRegistration.h +++ b/dom/workers/ServiceWorkerRegistration.h @@ -22,6 +22,7 @@ namespace dom { class Promise; class PushManager; +class WorkerPushManager; class WorkerListener; namespace workers { @@ -231,6 +232,9 @@ public: bool Notify(JSContext* aCx, workers::Status aStatus) override; + already_AddRefed + GetPushManager(ErrorResult& aRv); + private: enum Reason { @@ -248,6 +252,10 @@ private: workers::WorkerPrivate* mWorkerPrivate; nsRefPtr mListener; + +#ifndef MOZ_SIMPLEPUSH + nsRefPtr mPushManager; +#endif }; } // namespace dom diff --git a/dom/workers/test/serviceworkers/fetch/fetch_tests.js b/dom/workers/test/serviceworkers/fetch/fetch_tests.js index 1809eab7d07..53b80f7aa31 100644 --- a/dom/workers/test/serviceworkers/fetch/fetch_tests.js +++ b/dom/workers/test/serviceworkers/fetch/fetch_tests.js @@ -71,7 +71,7 @@ fetchXHR('synthesized-redirect-twice-synthesized.txt', function(xhr) { finish(); }); -fetchXHR('fetch/redirect.sjs', function(xhr) { +fetchXHR('redirect.sjs', function(xhr) { my_ok(xhr.status == 404, "redirected load should be uninterrupted"); finish(); }); diff --git a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js index 8c229aae1bc..09c8100b661 100644 --- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js +++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js @@ -171,6 +171,10 @@ var interfaceNamesInGlobalScope = "PerformanceMeasure", // IMPORTANT: Do not change this list without review from a DOM peer! "Promise", +// IMPORTANT: Do not change this list without review from a DOM peer! + "PushManager", +// IMPORTANT: Do not change this list without review from a DOM peer! + "PushSubscription", // IMPORTANT: Do not change this list without review from a DOM peer! "Request", // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/gfx/2d/PathHelpers.h b/gfx/2d/PathHelpers.h index 2aced30d1f0..ea142e3c63a 100644 --- a/gfx/2d/PathHelpers.h +++ b/gfx/2d/PathHelpers.h @@ -17,63 +17,50 @@ template void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius, float aStartAngle, float aEndAngle, bool aAntiClockwise) { - Point startPoint(aOrigin.x + cosf(aStartAngle) * aRadius.width, - aOrigin.y + sinf(aStartAngle) * aRadius.height); + Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f; - aSink->LineTo(startPoint); + // Calculate the total arc we're going to sweep. + Float arcSweepLeft = (aEndAngle - aStartAngle) * sweepDirection; // Clockwise we always sweep from the smaller to the larger angle, ccw // it's vice versa. - if (!aAntiClockwise && (aEndAngle < aStartAngle)) { - Float correction = Float(ceil((aStartAngle - aEndAngle) / (2.0f * M_PI))); - aEndAngle += float(correction * 2.0f * M_PI); - } else if (aAntiClockwise && (aStartAngle < aEndAngle)) { - Float correction = (Float)ceil((aEndAngle - aStartAngle) / (2.0f * M_PI)); - aStartAngle += float(correction * 2.0f * M_PI); + if (arcSweepLeft < 0) { + // Rerverse sweep is modulo'd into range rather than clamped. + arcSweepLeft = Float(2.0f * M_PI) + fmodf(arcSweepLeft, Float(2.0f * M_PI)); + // Recalculate the start angle to land closer to end angle. + aStartAngle = aEndAngle - arcSweepLeft * sweepDirection; + } else if (arcSweepLeft > Float(2.0f * M_PI)) { + // Sweeping more than 2 * pi is a full circle. + arcSweepLeft = Float(2.0f * M_PI); } - // Sweeping more than 2 * pi is a full circle. - if (!aAntiClockwise && (aEndAngle - aStartAngle > 2 * M_PI)) { - aEndAngle = float(aStartAngle + 2.0f * M_PI); - } else if (aAntiClockwise && (aStartAngle - aEndAngle > 2.0f * M_PI)) { - aEndAngle = float(aStartAngle - 2.0f * M_PI); - } - - // Calculate the total arc we're going to sweep. - Float arcSweepLeft = fabs(aEndAngle - aStartAngle); - - Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f; - Float currentStartAngle = aStartAngle; + Point currentStartPoint(aOrigin.x + cosf(aStartAngle) * aRadius.width, + aOrigin.y + sinf(aStartAngle) * aRadius.height); + + aSink->LineTo(currentStartPoint); while (arcSweepLeft > 0) { // We guarantee here the current point is the start point of the next // curve segment. - Float currentEndAngle; + Float currentEndAngle = + currentStartAngle + std::min(arcSweepLeft, Float(M_PI / 2.0f)) * sweepDirection; - if (arcSweepLeft > M_PI / 2.0f) { - currentEndAngle = Float(currentStartAngle + M_PI / 2.0f * sweepDirection); - } else { - currentEndAngle = currentStartAngle + arcSweepLeft * sweepDirection; - } - - Point currentStartPoint(aOrigin.x + cosf(currentStartAngle) * aRadius.width, - aOrigin.y + sinf(currentStartAngle) * aRadius.height); Point currentEndPoint(aOrigin.x + cosf(currentEndAngle) * aRadius.width, aOrigin.y + sinf(currentEndAngle) * aRadius.height); // Calculate kappa constant for partial curve. The sign of angle in the // tangent will actually ensure this is negative for a counter clockwise // sweep, so changing signs later isn't needed. - Float kappaFactor = (4.0f / 3.0f) * tan((currentEndAngle - currentStartAngle) / 4.0f); + Float kappaFactor = (4.0f / 3.0f) * tanf((currentEndAngle - currentStartAngle) / 4.0f); Float kappaX = kappaFactor * aRadius.width; Float kappaY = kappaFactor * aRadius.height; - Point tangentStart(-sin(currentStartAngle), cos(currentStartAngle)); + Point tangentStart(-sinf(currentStartAngle), cosf(currentStartAngle)); Point cp1 = currentStartPoint; cp1 += Point(tangentStart.x * kappaX, tangentStart.y * kappaY); - Point revTangentEnd(sin(currentEndAngle), -cos(currentEndAngle)); + Point revTangentEnd(sinf(currentEndAngle), -cosf(currentEndAngle)); Point cp2 = currentEndPoint; cp2 += Point(revTangentEnd.x * kappaX, revTangentEnd.y * kappaY); @@ -81,6 +68,7 @@ void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius, arcSweepLeft -= Float(M_PI / 2.0f); currentStartAngle = currentEndAngle; + currentStartPoint = currentEndPoint; } } diff --git a/gfx/cairo/cairo/src/cairo-atomic-private.h b/gfx/cairo/cairo/src/cairo-atomic-private.h index dd42a8ad135..c45d4506e96 100644 --- a/gfx/cairo/cairo/src/cairo-atomic-private.h +++ b/gfx/cairo/cairo/src/cairo-atomic-private.h @@ -45,6 +45,10 @@ #include "config.h" #endif +#if HAVE_WIN32_ATOMIC_PRIMITIVES +#include +#endif + /* The autoconf on OpenBSD 4.5 produces the malformed constant name * SIZEOF_VOID__ rather than SIZEOF_VOID_P. Work around that here. */ #if !defined(SIZEOF_VOID_P) && defined(SIZEOF_VOID__) @@ -143,6 +147,28 @@ _cairo_atomic_ptr_cmpxchg_return_old_impl(void **x, void *oldv, void *newv) #endif +#if HAVE_WIN32_ATOMIC_PRIMITIVES + +#define HAS_ATOMIC_OPS 1 + +typedef volatile long cairo_atomic_int_t; + +# define _cairo_atomic_int_get(x) ((int)*x) +# define _cairo_atomic_ptr_get(x) ((void*)*x) + +# define _cairo_atomic_int_inc(x) ((void) InterlockedIncrement(x)) +# define _cairo_atomic_int_dec(x) ((void) InterlockedDecrement(x)) +# define _cairo_atomic_int_dec_and_test(x) (InterlockedDecrement(x) == 0) +# define _cairo_atomic_int_cmpxchg(x, oldv, newv) (InterlockedCompareExchange(x, newv, oldv) == oldv) +# define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) InterlockedCompareExchange(x, newv, oldv) + +typedef volatile void* cairo_atomic_intptr_t; + +#define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) (InterlockedCompareExchangePointer(x, newv, oldv) == oldv) +#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) (InterlockedCompareExchangePointer(x, newv, oldv)) + +#endif + #if HAVE_INTEL_ATOMIC_PRIMITIVES #define HAS_ATOMIC_OPS 1 diff --git a/gfx/cairo/cairo/src/cairo-compiler-private.h b/gfx/cairo/cairo/src/cairo-compiler-private.h index 246f0a775bf..18dc661bda2 100644 --- a/gfx/cairo/cairo/src/cairo-compiler-private.h +++ b/gfx/cairo/cairo/src/cairo-compiler-private.h @@ -214,6 +214,9 @@ #endif #ifdef _MSC_VER + +#define HAVE_WIN32_ATOMIC_PRIMITIVES 1 + #ifndef __cplusplus #undef inline #define inline __inline diff --git a/gfx/cairo/cairo/src/cairo-reference-count-private.h b/gfx/cairo/cairo/src/cairo-reference-count-private.h index 0cb5695dd06..0d91488ee85 100644 --- a/gfx/cairo/cairo/src/cairo-reference-count-private.h +++ b/gfx/cairo/cairo/src/cairo-reference-count-private.h @@ -51,7 +51,7 @@ typedef struct { #define CAIRO_REFERENCE_COUNT_GET_VALUE(RC) _cairo_atomic_int_get (&(RC)->ref_count) -#define CAIRO_REFERENCE_COUNT_INVALID_VALUE ((cairo_atomic_int_t) -1) +#define CAIRO_REFERENCE_COUNT_INVALID_VALUE (-1) #define CAIRO_REFERENCE_COUNT_INVALID {CAIRO_REFERENCE_COUNT_INVALID_VALUE} #define CAIRO_REFERENCE_COUNT_IS_INVALID(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) == CAIRO_REFERENCE_COUNT_INVALID_VALUE) diff --git a/gfx/layers/apz/util/APZEventState.cpp b/gfx/layers/apz/util/APZEventState.cpp index 656d29e13dd..0c67d71b062 100644 --- a/gfx/layers/apz/util/APZEventState.cpp +++ b/gfx/layers/apz/util/APZEventState.cpp @@ -216,7 +216,7 @@ APZEventState::ProcessLongTap(const nsCOMPtr& aPresShell, return; } - SendPendingTouchPreventedResponse(false, aGuid); + SendPendingTouchPreventedResponse(false); // Converting the modifiers to DOM format for the DispatchMouseEvent call // is the most useless thing ever because nsDOMWindowUtils::SendMouseEvent @@ -290,7 +290,10 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent, mActiveElementManager->HandleTouchEndEvent(mEndTouchIsClick); // fall through case NS_TOUCH_MOVE: { - sentContentResponse = SendPendingTouchPreventedResponse(isTouchPrevented, aGuid); + if (mPendingTouchPreventedResponse) { + MOZ_ASSERT(aGuid == mPendingTouchPreventedGuid); + } + sentContentResponse = SendPendingTouchPreventedResponse(isTouchPrevented); break; } @@ -396,11 +399,9 @@ APZEventState::ProcessAPZStateChange(const nsCOMPtr& aDocument, } bool -APZEventState::SendPendingTouchPreventedResponse(bool aPreventDefault, - const ScrollableLayerGuid& aGuid) +APZEventState::SendPendingTouchPreventedResponse(bool aPreventDefault) { if (mPendingTouchPreventedResponse) { - MOZ_ASSERT(aGuid == mPendingTouchPreventedGuid); mContentReceivedInputBlockCallback->Run(mPendingTouchPreventedGuid, mPendingTouchPreventedBlockId, aPreventDefault); mPendingTouchPreventedResponse = false; diff --git a/gfx/layers/apz/util/APZEventState.h b/gfx/layers/apz/util/APZEventState.h index 9a099f4cf67..539363d37c4 100644 --- a/gfx/layers/apz/util/APZEventState.h +++ b/gfx/layers/apz/util/APZEventState.h @@ -71,8 +71,7 @@ public: int aArg); private: ~APZEventState(); - bool SendPendingTouchPreventedResponse(bool aPreventDefault, - const ScrollableLayerGuid& aGuid); + bool SendPendingTouchPreventedResponse(bool aPreventDefault); already_AddRefed GetWidget() const; private: nsWeakPtr mWidget; diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index c1447cfebde..9c9ab080f9b 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -167,6 +167,11 @@ CompositorOGL::CleanupResources() if (!mGLContext) return; +#ifdef MOZ_WIDGET_GONK + mWidget->SetNativeData(NS_NATIVE_OPENGL_CONTEXT, + reinterpret_cast(nullptr)); +#endif + nsRefPtr ctx = mGLContext->GetSharedContext(); if (!ctx) { ctx = mGLContext; diff --git a/hal/Hal.cpp b/hal/Hal.cpp index 316de7e69ce..e1f2d937fab 100644 --- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -202,7 +202,6 @@ public: void RemoveObserver(Observer* aObserver) { bool removed = mObservers && mObservers->RemoveObserver(aObserver); if (!removed) { - NS_WARNING("RemoveObserver() called for unregistered observer"); return; } diff --git a/js/src/asmjs/AsmJSModule.cpp b/js/src/asmjs/AsmJSModule.cpp index 446fbdd46bd..b8fcc8a30cb 100644 --- a/js/src/asmjs/AsmJSModule.cpp +++ b/js/src/asmjs/AsmJSModule.cpp @@ -1742,6 +1742,13 @@ AsmJSModule::changeHeap(Handle newHeap, JSContext* cx) return true; } +size_t +AsmJSModule::heapLength() const +{ + MOZ_ASSERT(isDynamicallyLinked()); + return maybeHeap_ ? maybeHeap_->byteLength() : 0; +} + void AsmJSModule::setProfilingEnabled(bool enabled, JSContext* cx) { diff --git a/js/src/asmjs/AsmJSModule.h b/js/src/asmjs/AsmJSModule.h index 0712e0450eb..3b930d600dc 100644 --- a/js/src/asmjs/AsmJSModule.h +++ b/js/src/asmjs/AsmJSModule.h @@ -1571,10 +1571,7 @@ class AsmJSModule MOZ_ASSERT(isDynamicallyLinked()); return maybeHeap_; } - size_t heapLength() const { - MOZ_ASSERT(isDynamicallyLinked()); - return maybeHeap_ ? maybeHeap_->byteLength() : 0; - } + size_t heapLength() const; bool profilingEnabled() const { MOZ_ASSERT(isDynamicallyLinked()); return profilingEnabled_; diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index 60504bcb039..9a2533af56d 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -6,12 +6,11 @@ #include "builtin/MapObject.h" -#include "mozilla/Move.h" - #include "jscntxt.h" #include "jsiter.h" #include "jsobj.h" +#include "ds/OrderedHashTable.h" #include "gc/Marking.h" #include "js/Utility.h" #include "vm/GlobalObject.h" @@ -25,757 +24,12 @@ using namespace js; using mozilla::ArrayLength; -using mozilla::Forward; using mozilla::IsNaN; -using mozilla::Move; using mozilla::NumberEqualsInt32; using JS::DoubleNaNValue; using JS::ForOfIterator; - -/*** OrderedHashTable ****************************************************************************/ - -/* - * Define two collection templates, js::OrderedHashMap and js::OrderedHashSet. - * They are like js::HashMap and js::HashSet except that: - * - * - Iterating over an Ordered hash table visits the entries in the order in - * which they were inserted. This means that unlike a HashMap, the behavior - * of an OrderedHashMap is deterministic (as long as the HashPolicy methods - * are effect-free and consistent); the hashing is a pure performance - * optimization. - * - * - Range objects over Ordered tables remain valid even when entries are - * added or removed or the table is resized. (However in the case of - * removing entries, note the warning on class Range below.) - * - * - The API is a little different, so it's not a drop-in replacement. - * In particular, the hash policy is a little different. - * Also, the Ordered templates lack the Ptr and AddPtr types. - * - * Hash policies - * - * See the comment about "Hash policy" in HashTable.h for general features that - * hash policy classes must provide. Hash policies for OrderedHashMaps and Sets - * must additionally provide a distinguished "empty" key value and the - * following static member functions: - * bool isEmpty(const Key&); - * void makeEmpty(Key*); - */ - -namespace js { - -namespace detail { - -/* - * detail::OrderedHashTable is the underlying data structure used to implement both - * OrderedHashMap and OrderedHashSet. Programs should use one of those two - * templates rather than OrderedHashTable. - */ -template -class OrderedHashTable -{ - public: - typedef typename Ops::KeyType Key; - typedef typename Ops::Lookup Lookup; - - struct Data - { - T element; - Data* chain; - - Data(const T& e, Data* c) : element(e), chain(c) {} - Data(T&& e, Data* c) : element(Move(e)), chain(c) {} - }; - - class Range; - friend class Range; - - private: - Data** hashTable; // hash table (has hashBuckets() elements) - Data* data; // data vector, an array of Data objects - // data[0:dataLength] are constructed - uint32_t dataLength; // number of constructed elements in data - uint32_t dataCapacity; // size of data, in elements - uint32_t liveCount; // dataLength less empty (removed) entries - uint32_t hashShift; // multiplicative hash shift - Range* ranges; // list of all live Ranges on this table - AllocPolicy alloc; - - public: - explicit OrderedHashTable(AllocPolicy& ap) - : hashTable(nullptr), data(nullptr), dataLength(0), ranges(nullptr), alloc(ap) {} - - bool init() { - MOZ_ASSERT(!hashTable, "init must be called at most once"); - - uint32_t buckets = initialBuckets(); - Data** tableAlloc = alloc.template pod_malloc(buckets); - if (!tableAlloc) - return false; - for (uint32_t i = 0; i < buckets; i++) - tableAlloc[i] = nullptr; - - uint32_t capacity = uint32_t(buckets * fillFactor()); - Data* dataAlloc = alloc.template pod_malloc(capacity); - if (!dataAlloc) { - alloc.free_(tableAlloc); - return false; - } - - // clear() requires that members are assigned only after all allocation - // has succeeded, and that this->ranges is left untouched. - hashTable = tableAlloc; - data = dataAlloc; - dataLength = 0; - dataCapacity = capacity; - liveCount = 0; - hashShift = HashNumberSizeBits - initialBucketsLog2(); - MOZ_ASSERT(hashBuckets() == buckets); - return true; - } - - ~OrderedHashTable() { - for (Range* r = ranges; r; ) { - Range* next = r->next; - r->onTableDestroyed(); - r = next; - } - alloc.free_(hashTable); - freeData(data, dataLength); - } - - /* Return the number of elements in the table. */ - uint32_t count() const { return liveCount; } - - /* True if any element matches l. */ - bool has(const Lookup& l) const { - return lookup(l) != nullptr; - } - - /* Return a pointer to the element, if any, that matches l, or nullptr. */ - T* get(const Lookup& l) { - Data* e = lookup(l, prepareHash(l)); - return e ? &e->element : nullptr; - } - - /* Return a pointer to the element, if any, that matches l, or nullptr. */ - const T* get(const Lookup& l) const { - return const_cast(this)->get(l); - } - - /* - * If the table already contains an entry that matches |element|, - * replace that entry with |element|. Otherwise add a new entry. - * - * On success, return true, whether there was already a matching element or - * not. On allocation failure, return false. If this returns false, it - * means the element was not added to the table. - */ - template - bool put(ElementInput&& element) { - HashNumber h = prepareHash(Ops::getKey(element)); - if (Data* e = lookup(Ops::getKey(element), h)) { - e->element = Forward(element); - return true; - } - - if (dataLength == dataCapacity) { - // If the hashTable is more than 1/4 deleted data, simply rehash in - // place to free up some space. Otherwise, grow the table. - uint32_t newHashShift = liveCount >= dataCapacity * 0.75 ? hashShift - 1 : hashShift; - if (!rehash(newHashShift)) - return false; - } - - h >>= hashShift; - liveCount++; - Data* e = &data[dataLength++]; - new (e) Data(Forward(element), hashTable[h]); - hashTable[h] = e; - return true; - } - - /* - * If the table contains an element matching l, remove it and set *foundp - * to true. Otherwise set *foundp to false. - * - * Return true on success, false if we tried to shrink the table and hit an - * allocation failure. Even if this returns false, *foundp is set correctly - * and the matching element was removed. Shrinking is an optimization and - * it's OK for it to fail. - */ - bool remove(const Lookup& l, bool* foundp) { - // Note: This could be optimized so that removing the last entry, - // data[dataLength - 1], decrements dataLength. LIFO use cases would - // benefit. - - // If a matching entry exists, empty it. - Data* e = lookup(l, prepareHash(l)); - if (e == nullptr) { - *foundp = false; - return true; - } - - *foundp = true; - liveCount--; - Ops::makeEmpty(&e->element); - - // Update active Ranges. - uint32_t pos = e - data; - for (Range* r = ranges; r; r = r->next) - r->onRemove(pos); - - // If many entries have been removed, try to shrink the table. - if (hashBuckets() > initialBuckets() && liveCount < dataLength * minDataFill()) { - if (!rehash(hashShift + 1)) - return false; - } - return true; - } - - /* - * Remove all entries. - * - * Returns false on OOM, leaving the OrderedHashTable and any live Ranges - * in the old state. - * - * The effect on live Ranges is the same as removing all entries; in - * particular, those Ranges are still live and will see any entries added - * after a successful clear(). - */ - bool clear() { - if (dataLength != 0) { - Data** oldHashTable = hashTable; - Data* oldData = data; - uint32_t oldDataLength = dataLength; - - hashTable = nullptr; - if (!init()) { - // init() only mutates members on success; see comment above. - hashTable = oldHashTable; - return false; - } - - alloc.free_(oldHashTable); - freeData(oldData, oldDataLength); - for (Range* r = ranges; r; r = r->next) - r->onClear(); - } - - MOZ_ASSERT(hashTable); - MOZ_ASSERT(data); - MOZ_ASSERT(dataLength == 0); - MOZ_ASSERT(liveCount == 0); - return true; - } - - /* - * Ranges are used to iterate over OrderedHashTables. - * - * Suppose 'Map' is some instance of OrderedHashMap, and 'map' is a Map. - * Then you can walk all the key-value pairs like this: - * - * for (Map::Range r = map.all(); !r.empty(); r.popFront()) { - * Map::Entry& pair = r.front(); - * ... do something with pair ... - * } - * - * Ranges remain valid for the lifetime of the OrderedHashTable, even if - * entries are added or removed or the table is resized. Don't do anything - * to a Range, except destroy it, after the OrderedHashTable has been - * destroyed. (We support destroying the two objects in either order to - * humor the GC, bless its nondeterministic heart.) - * - * Warning: The behavior when the current front() entry is removed from the - * table is subtly different from js::HashTable<>::Enum::removeFront()! - * HashTable::Enum doesn't skip any entries when you removeFront() and then - * popFront(). OrderedHashTable::Range does! (This is useful for using a - * Range to implement JS Map.prototype.iterator.) - * - * The workaround is to call popFront() as soon as possible, - * before there's any possibility of modifying the table: - * - * for (Map::Range r = map.all(); !r.empty(); ) { - * Key key = r.front().key; // this won't modify map - * Value val = r.front().value; // this won't modify map - * r.popFront(); - * // ...do things that might modify map... - * } - */ - class Range - { - friend class OrderedHashTable; - - OrderedHashTable& ht; - - /* The index of front() within ht.data. */ - uint32_t i; - - /* - * The number of nonempty entries in ht.data to the left of front(). - * This is used when the table is resized or compacted. - */ - uint32_t count; - - /* - * Links in the doubly-linked list of active Ranges on ht. - * - * prevp points to the previous Range's .next field; - * or to ht.ranges if this is the first Range in the list. - * next points to the next Range; - * or nullptr if this is the last Range in the list. - * - * Invariant: *prevp == this. - */ - Range** prevp; - Range* next; - - /* - * Create a Range over all the entries in ht. - * (This is private on purpose. End users must use ht.all().) - */ - explicit Range(OrderedHashTable& ht) : ht(ht), i(0), count(0), prevp(&ht.ranges), next(ht.ranges) { - *prevp = this; - if (next) - next->prevp = &next; - seek(); - } - - public: - Range(const Range& other) - : ht(other.ht), i(other.i), count(other.count), prevp(&ht.ranges), next(ht.ranges) - { - *prevp = this; - if (next) - next->prevp = &next; - } - - ~Range() { - *prevp = next; - if (next) - next->prevp = prevp; - } - - private: - // Prohibit copy assignment. - Range& operator=(const Range& other) = delete; - - void seek() { - while (i < ht.dataLength && Ops::isEmpty(Ops::getKey(ht.data[i].element))) - i++; - } - - /* - * The hash table calls this when an entry is removed. - * j is the index of the removed entry. - */ - void onRemove(uint32_t j) { - MOZ_ASSERT(valid()); - if (j < i) - count--; - if (j == i) - seek(); - } - - /* - * The hash table calls this when the table is resized or compacted. - * Since |count| is the number of nonempty entries to the left of - * front(), discarding the empty entries will not affect count, and it - * will make i and count equal. - */ - void onCompact() { - MOZ_ASSERT(valid()); - i = count; - } - - /* The hash table calls this when cleared. */ - void onClear() { - MOZ_ASSERT(valid()); - i = count = 0; - } - - bool valid() const { - return next != this; - } - - void onTableDestroyed() { - MOZ_ASSERT(valid()); - prevp = &next; - next = this; - } - - public: - bool empty() const { - MOZ_ASSERT(valid()); - return i >= ht.dataLength; - } - - /* - * Return the first element in the range. This must not be called if - * this->empty(). - * - * Warning: Removing an entry from the table also removes it from any - * live Ranges, and a Range can become empty that way, rendering - * front() invalid. If in doubt, check empty() before calling front(). - */ - T& front() { - MOZ_ASSERT(valid()); - MOZ_ASSERT(!empty()); - return ht.data[i].element; - } - - /* - * Remove the first element from this range. - * This must not be called if this->empty(). - * - * Warning: Removing an entry from the table also removes it from any - * live Ranges, and a Range can become empty that way, rendering - * popFront() invalid. If in doubt, check empty() before calling - * popFront(). - */ - void popFront() { - MOZ_ASSERT(valid()); - MOZ_ASSERT(!empty()); - MOZ_ASSERT(!Ops::isEmpty(Ops::getKey(ht.data[i].element))); - count++; - i++; - seek(); - } - - /* - * Change the key of the front entry. - * - * This calls Ops::hash on both the current key and the new key. - * Ops::hash on the current key must return the same hash code as - * when the entry was added to the table. - */ - void rekeyFront(const Key& k) { - MOZ_ASSERT(valid()); - Data& entry = ht.data[i]; - HashNumber oldHash = prepareHash(Ops::getKey(entry.element)) >> ht.hashShift; - HashNumber newHash = prepareHash(k) >> ht.hashShift; - Ops::setKey(entry.element, k); - if (newHash != oldHash) { - // Remove this entry from its old hash chain. (If this crashes - // reading nullptr, it would mean we did not find this entry on - // the hash chain where we expected it. That probably means the - // key's hash code changed since it was inserted, breaking the - // hash code invariant.) - Data** ep = &ht.hashTable[oldHash]; - while (*ep != &entry) - ep = &(*ep)->chain; - *ep = entry.chain; - - // Add it to the new hash chain. We could just insert it at the - // beginning of the chain. Instead, we do a bit of work to - // preserve the invariant that hash chains always go in reverse - // insertion order (descending memory order). No code currently - // depends on this invariant, so it's fine to kill it if - // needed. - ep = &ht.hashTable[newHash]; - while (*ep && *ep > &entry) - ep = &(*ep)->chain; - entry.chain = *ep; - *ep = &entry; - } - } - }; - - Range all() { return Range(*this); } - - /* - * Change the value of the given key. - * - * This calls Ops::hash on both the current key and the new key. - * Ops::hash on the current key must return the same hash code as - * when the entry was added to the table. - */ - void rekeyOneEntry(const Key& current, const Key& newKey, const T& element) { - if (current == newKey) - return; - - Data* entry = lookup(current, prepareHash(current)); - if (!entry) - return; - - HashNumber oldHash = prepareHash(current) >> hashShift; - HashNumber newHash = prepareHash(newKey) >> hashShift; - - entry->element = element; - - // Remove this entry from its old hash chain. (If this crashes - // reading nullptr, it would mean we did not find this entry on - // the hash chain where we expected it. That probably means the - // key's hash code changed since it was inserted, breaking the - // hash code invariant.) - Data** ep = &hashTable[oldHash]; - while (*ep != entry) - ep = &(*ep)->chain; - *ep = entry->chain; - - // Add it to the new hash chain. We could just insert it at the - // beginning of the chain. Instead, we do a bit of work to - // preserve the invariant that hash chains always go in reverse - // insertion order (descending memory order). No code currently - // depends on this invariant, so it's fine to kill it if - // needed. - ep = &hashTable[newHash]; - while (*ep && *ep > entry) - ep = &(*ep)->chain; - entry->chain = *ep; - *ep = entry; - } - - private: - /* Logarithm base 2 of the number of buckets in the hash table initially. */ - static uint32_t initialBucketsLog2() { return 1; } - static uint32_t initialBuckets() { return 1 << initialBucketsLog2(); } - - /* - * The maximum load factor (mean number of entries per bucket). - * It is an invariant that - * dataCapacity == floor(hashBuckets() * fillFactor()). - * - * The fill factor should be between 2 and 4, and it should be chosen so that - * the fill factor times sizeof(Data) is close to but <= a power of 2. - * This fixed fill factor was chosen to make the size of the data - * array, in bytes, close to a power of two when sizeof(T) is 16. - */ - static double fillFactor() { return 8.0 / 3.0; } - - /* - * The minimum permitted value of (liveCount / dataLength). - * If that ratio drops below this value, we shrink the table. - */ - static double minDataFill() { return 0.25; } - - static HashNumber prepareHash(const Lookup& l) { - return ScrambleHashCode(Ops::hash(l)); - } - - /* The size of hashTable, in elements. Always a power of two. */ - uint32_t hashBuckets() const { - return 1 << (HashNumberSizeBits - hashShift); - } - - static void destroyData(Data* data, uint32_t length) { - for (Data* p = data + length; p != data; ) - (--p)->~Data(); - } - - void freeData(Data* data, uint32_t length) { - destroyData(data, length); - alloc.free_(data); - } - - Data* lookup(const Lookup& l, HashNumber h) { - for (Data* e = hashTable[h >> hashShift]; e; e = e->chain) { - if (Ops::match(Ops::getKey(e->element), l)) - return e; - } - return nullptr; - } - - const Data* lookup(const Lookup& l) const { - return const_cast(this)->lookup(l, prepareHash(l)); - } - - /* This is called after rehashing the table. */ - void compacted() { - // If we had any empty entries, compacting may have moved live entries - // to the left within |data|. Notify all live Ranges of the change. - for (Range* r = ranges; r; r = r->next) - r->onCompact(); - } - - /* Compact the entries in |data| and rehash them. */ - void rehashInPlace() { - for (uint32_t i = 0, N = hashBuckets(); i < N; i++) - hashTable[i] = nullptr; - Data* wp = data; - Data* end = data + dataLength; - for (Data* rp = data; rp != end; rp++) { - if (!Ops::isEmpty(Ops::getKey(rp->element))) { - HashNumber h = prepareHash(Ops::getKey(rp->element)) >> hashShift; - if (rp != wp) - wp->element = Move(rp->element); - wp->chain = hashTable[h]; - hashTable[h] = wp; - wp++; - } - } - MOZ_ASSERT(wp == data + liveCount); - - while (wp != end) - (--end)->~Data(); - dataLength = liveCount; - compacted(); - } - - /* - * Grow, shrink, or compact both |hashTable| and |data|. - * - * On success, this returns true, dataLength == liveCount, and there are no - * empty elements in data[0:dataLength]. On allocation failure, this - * leaves everything as it was and returns false. - */ - bool rehash(uint32_t newHashShift) { - // If the size of the table is not changing, rehash in place to avoid - // allocating memory. - if (newHashShift == hashShift) { - rehashInPlace(); - return true; - } - - size_t newHashBuckets = 1 << (HashNumberSizeBits - newHashShift); - Data** newHashTable = alloc.template pod_malloc(newHashBuckets); - if (!newHashTable) - return false; - for (uint32_t i = 0; i < newHashBuckets; i++) - newHashTable[i] = nullptr; - - uint32_t newCapacity = uint32_t(newHashBuckets * fillFactor()); - Data* newData = alloc.template pod_malloc(newCapacity); - if (!newData) { - alloc.free_(newHashTable); - return false; - } - - Data* wp = newData; - Data* end = data + dataLength; - for (Data* p = data; p != end; p++) { - if (!Ops::isEmpty(Ops::getKey(p->element))) { - HashNumber h = prepareHash(Ops::getKey(p->element)) >> newHashShift; - new (wp) Data(Move(p->element), newHashTable[h]); - newHashTable[h] = wp; - wp++; - } - } - MOZ_ASSERT(wp == newData + liveCount); - - alloc.free_(hashTable); - freeData(data, dataLength); - - hashTable = newHashTable; - data = newData; - dataLength = liveCount; - dataCapacity = newCapacity; - hashShift = newHashShift; - MOZ_ASSERT(hashBuckets() == newHashBuckets); - - compacted(); - return true; - } - - // Not copyable. - OrderedHashTable& operator=(const OrderedHashTable&) = delete; - OrderedHashTable(const OrderedHashTable&) = delete; -}; - -} // namespace detail - -template -class OrderedHashMap -{ - public: - class Entry - { - template friend class detail::OrderedHashTable; - void operator=(const Entry& rhs) { - const_cast(key) = rhs.key; - value = rhs.value; - } - - void operator=(Entry&& rhs) { - MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); - const_cast(key) = Move(rhs.key); - value = Move(rhs.value); - } - - public: - Entry() : key(), value() {} - Entry(const Key& k, const Value& v) : key(k), value(v) {} - Entry(Entry&& rhs) : key(Move(rhs.key)), value(Move(rhs.value)) {} - - const Key key; - Value value; - }; - - private: - struct MapOps : OrderedHashPolicy - { - typedef Key KeyType; - static void makeEmpty(Entry* e) { - OrderedHashPolicy::makeEmpty(const_cast(&e->key)); - - // Clear the value. Destroying it is another possibility, but that - // would complicate class Entry considerably. - e->value = Value(); - } - static const Key& getKey(const Entry& e) { return e.key; } - static void setKey(Entry& e, const Key& k) { const_cast(e.key) = k; } - }; - - typedef detail::OrderedHashTable Impl; - Impl impl; - - public: - typedef typename Impl::Range Range; - - explicit OrderedHashMap(AllocPolicy ap = AllocPolicy()) : impl(ap) {} - bool init() { return impl.init(); } - uint32_t count() const { return impl.count(); } - bool has(const Key& key) const { return impl.has(key); } - Range all() { return impl.all(); } - const Entry* get(const Key& key) const { return impl.get(key); } - Entry* get(const Key& key) { return impl.get(key); } - bool put(const Key& key, const Value& value) { return impl.put(Entry(key, value)); } - bool remove(const Key& key, bool* foundp) { return impl.remove(key, foundp); } - bool clear() { return impl.clear(); } - - void rekeyOneEntry(const Key& current, const Key& newKey) { - const Entry* e = get(current); - if (!e) - return; - return impl.rekeyOneEntry(current, newKey, Entry(newKey, e->value)); - } -}; - -template -class OrderedHashSet -{ - private: - struct SetOps : OrderedHashPolicy - { - typedef const T KeyType; - static const T& getKey(const T& v) { return v; } - static void setKey(const T& e, const T& v) { const_cast(e) = v; } - }; - - typedef detail::OrderedHashTable Impl; - Impl impl; - - public: - typedef typename Impl::Range Range; - - explicit OrderedHashSet(AllocPolicy ap = AllocPolicy()) : impl(ap) {} - bool init() { return impl.init(); } - uint32_t count() const { return impl.count(); } - bool has(const T& value) const { return impl.has(value); } - Range all() { return impl.all(); } - bool put(const T& value) { return impl.put(value); } - bool remove(const T& value, bool* foundp) { return impl.remove(value, foundp); } - bool clear() { return impl.clear(); } - - void rekeyOneEntry(const T& current, const T& newKey) { - return impl.rekeyOneEntry(current, newKey, newKey); - } -}; - -} // namespace js - /*** HashableValue *******************************************************************************/ diff --git a/js/src/builtin/Reflect.cpp b/js/src/builtin/Reflect.cpp index f82a093decf..2a6eb471bf4 100644 --- a/js/src/builtin/Reflect.cpp +++ b/js/src/builtin/Reflect.cpp @@ -6,10 +6,14 @@ #include "builtin/Reflect.h" +#include "jsarray.h" #include "jscntxt.h" +#include "vm/ArgumentsObject.h" #include "vm/Stack.h" +#include "vm/Interpreter-inl.h" + using namespace js; diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 9c334be1bec..a0e4bb33f54 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -1455,7 +1455,7 @@ js::testingFunc_inIon(JSContext* cx, unsigned argc, Value* vp) ScriptFrameIter iter(cx); if (iter.isIon()) { // Reset the counter of the IonScript's script. - JitFrameIterator jitIter(cx); + jit::JitFrameIterator jitIter(cx); ++jitIter; jitIter.script()->resetWarmUpResetCounter(); } else { diff --git a/js/src/ds/OrderedHashTable.h b/js/src/ds/OrderedHashTable.h new file mode 100644 index 00000000000..8b12367e554 --- /dev/null +++ b/js/src/ds/OrderedHashTable.h @@ -0,0 +1,755 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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 http://mozilla.org/MPL/2.0/. */ + +#ifndef ds_OrderedHashTable_h +#define ds_OrderedHashTable_h + +/* + * Define two collection templates, js::OrderedHashMap and js::OrderedHashSet. + * They are like js::HashMap and js::HashSet except that: + * + * - Iterating over an Ordered hash table visits the entries in the order in + * which they were inserted. This means that unlike a HashMap, the behavior + * of an OrderedHashMap is deterministic (as long as the HashPolicy methods + * are effect-free and consistent); the hashing is a pure performance + * optimization. + * + * - Range objects over Ordered tables remain valid even when entries are + * added or removed or the table is resized. (However in the case of + * removing entries, note the warning on class Range below.) + * + * - The API is a little different, so it's not a drop-in replacement. + * In particular, the hash policy is a little different. + * Also, the Ordered templates lack the Ptr and AddPtr types. + * + * Hash policies + * + * See the comment about "Hash policy" in HashTable.h for general features that + * hash policy classes must provide. Hash policies for OrderedHashMaps and Sets + * must additionally provide a distinguished "empty" key value and the + * following static member functions: + * bool isEmpty(const Key&); + * void makeEmpty(Key*); + */ + +#include "mozilla/Move.h" + +using mozilla::Forward; +using mozilla::Move; + +namespace js { + +namespace detail { + +/* + * detail::OrderedHashTable is the underlying data structure used to implement both + * OrderedHashMap and OrderedHashSet. Programs should use one of those two + * templates rather than OrderedHashTable. + */ +template +class OrderedHashTable +{ + public: + typedef typename Ops::KeyType Key; + typedef typename Ops::Lookup Lookup; + + struct Data + { + T element; + Data* chain; + + Data(const T& e, Data* c) : element(e), chain(c) {} + Data(T&& e, Data* c) : element(Move(e)), chain(c) {} + }; + + class Range; + friend class Range; + + private: + Data** hashTable; // hash table (has hashBuckets() elements) + Data* data; // data vector, an array of Data objects + // data[0:dataLength] are constructed + uint32_t dataLength; // number of constructed elements in data + uint32_t dataCapacity; // size of data, in elements + uint32_t liveCount; // dataLength less empty (removed) entries + uint32_t hashShift; // multiplicative hash shift + Range* ranges; // list of all live Ranges on this table + AllocPolicy alloc; + + public: + explicit OrderedHashTable(AllocPolicy& ap) + : hashTable(nullptr), data(nullptr), dataLength(0), ranges(nullptr), alloc(ap) {} + + bool init() { + MOZ_ASSERT(!hashTable, "init must be called at most once"); + + uint32_t buckets = initialBuckets(); + Data** tableAlloc = alloc.template pod_malloc(buckets); + if (!tableAlloc) + return false; + for (uint32_t i = 0; i < buckets; i++) + tableAlloc[i] = nullptr; + + uint32_t capacity = uint32_t(buckets * fillFactor()); + Data* dataAlloc = alloc.template pod_malloc(capacity); + if (!dataAlloc) { + alloc.free_(tableAlloc); + return false; + } + + // clear() requires that members are assigned only after all allocation + // has succeeded, and that this->ranges is left untouched. + hashTable = tableAlloc; + data = dataAlloc; + dataLength = 0; + dataCapacity = capacity; + liveCount = 0; + hashShift = HashNumberSizeBits - initialBucketsLog2(); + MOZ_ASSERT(hashBuckets() == buckets); + return true; + } + + ~OrderedHashTable() { + for (Range* r = ranges; r; ) { + Range* next = r->next; + r->onTableDestroyed(); + r = next; + } + alloc.free_(hashTable); + freeData(data, dataLength); + } + + /* Return the number of elements in the table. */ + uint32_t count() const { return liveCount; } + + /* True if any element matches l. */ + bool has(const Lookup& l) const { + return lookup(l) != nullptr; + } + + /* Return a pointer to the element, if any, that matches l, or nullptr. */ + T* get(const Lookup& l) { + Data* e = lookup(l, prepareHash(l)); + return e ? &e->element : nullptr; + } + + /* Return a pointer to the element, if any, that matches l, or nullptr. */ + const T* get(const Lookup& l) const { + return const_cast(this)->get(l); + } + + /* + * If the table already contains an entry that matches |element|, + * replace that entry with |element|. Otherwise add a new entry. + * + * On success, return true, whether there was already a matching element or + * not. On allocation failure, return false. If this returns false, it + * means the element was not added to the table. + */ + template + bool put(ElementInput&& element) { + HashNumber h = prepareHash(Ops::getKey(element)); + if (Data* e = lookup(Ops::getKey(element), h)) { + e->element = Forward(element); + return true; + } + + if (dataLength == dataCapacity) { + // If the hashTable is more than 1/4 deleted data, simply rehash in + // place to free up some space. Otherwise, grow the table. + uint32_t newHashShift = liveCount >= dataCapacity * 0.75 ? hashShift - 1 : hashShift; + if (!rehash(newHashShift)) + return false; + } + + h >>= hashShift; + liveCount++; + Data* e = &data[dataLength++]; + new (e) Data(Forward(element), hashTable[h]); + hashTable[h] = e; + return true; + } + + /* + * If the table contains an element matching l, remove it and set *foundp + * to true. Otherwise set *foundp to false. + * + * Return true on success, false if we tried to shrink the table and hit an + * allocation failure. Even if this returns false, *foundp is set correctly + * and the matching element was removed. Shrinking is an optimization and + * it's OK for it to fail. + */ + bool remove(const Lookup& l, bool* foundp) { + // Note: This could be optimized so that removing the last entry, + // data[dataLength - 1], decrements dataLength. LIFO use cases would + // benefit. + + // If a matching entry exists, empty it. + Data* e = lookup(l, prepareHash(l)); + if (e == nullptr) { + *foundp = false; + return true; + } + + *foundp = true; + liveCount--; + Ops::makeEmpty(&e->element); + + // Update active Ranges. + uint32_t pos = e - data; + for (Range* r = ranges; r; r = r->next) + r->onRemove(pos); + + // If many entries have been removed, try to shrink the table. + if (hashBuckets() > initialBuckets() && liveCount < dataLength * minDataFill()) { + if (!rehash(hashShift + 1)) + return false; + } + return true; + } + + /* + * Remove all entries. + * + * Returns false on OOM, leaving the OrderedHashTable and any live Ranges + * in the old state. + * + * The effect on live Ranges is the same as removing all entries; in + * particular, those Ranges are still live and will see any entries added + * after a successful clear(). + */ + bool clear() { + if (dataLength != 0) { + Data** oldHashTable = hashTable; + Data* oldData = data; + uint32_t oldDataLength = dataLength; + + hashTable = nullptr; + if (!init()) { + // init() only mutates members on success; see comment above. + hashTable = oldHashTable; + return false; + } + + alloc.free_(oldHashTable); + freeData(oldData, oldDataLength); + for (Range* r = ranges; r; r = r->next) + r->onClear(); + } + + MOZ_ASSERT(hashTable); + MOZ_ASSERT(data); + MOZ_ASSERT(dataLength == 0); + MOZ_ASSERT(liveCount == 0); + return true; + } + + /* + * Ranges are used to iterate over OrderedHashTables. + * + * Suppose 'Map' is some instance of OrderedHashMap, and 'map' is a Map. + * Then you can walk all the key-value pairs like this: + * + * for (Map::Range r = map.all(); !r.empty(); r.popFront()) { + * Map::Entry& pair = r.front(); + * ... do something with pair ... + * } + * + * Ranges remain valid for the lifetime of the OrderedHashTable, even if + * entries are added or removed or the table is resized. Don't do anything + * to a Range, except destroy it, after the OrderedHashTable has been + * destroyed. (We support destroying the two objects in either order to + * humor the GC, bless its nondeterministic heart.) + * + * Warning: The behavior when the current front() entry is removed from the + * table is subtly different from js::HashTable<>::Enum::removeFront()! + * HashTable::Enum doesn't skip any entries when you removeFront() and then + * popFront(). OrderedHashTable::Range does! (This is useful for using a + * Range to implement JS Map.prototype.iterator.) + * + * The workaround is to call popFront() as soon as possible, + * before there's any possibility of modifying the table: + * + * for (Map::Range r = map.all(); !r.empty(); ) { + * Key key = r.front().key; // this won't modify map + * Value val = r.front().value; // this won't modify map + * r.popFront(); + * // ...do things that might modify map... + * } + */ + class Range + { + friend class OrderedHashTable; + + OrderedHashTable& ht; + + /* The index of front() within ht.data. */ + uint32_t i; + + /* + * The number of nonempty entries in ht.data to the left of front(). + * This is used when the table is resized or compacted. + */ + uint32_t count; + + /* + * Links in the doubly-linked list of active Ranges on ht. + * + * prevp points to the previous Range's .next field; + * or to ht.ranges if this is the first Range in the list. + * next points to the next Range; + * or nullptr if this is the last Range in the list. + * + * Invariant: *prevp == this. + */ + Range** prevp; + Range* next; + + /* + * Create a Range over all the entries in ht. + * (This is private on purpose. End users must use ht.all().) + */ + explicit Range(OrderedHashTable& ht) : ht(ht), i(0), count(0), prevp(&ht.ranges), next(ht.ranges) { + *prevp = this; + if (next) + next->prevp = &next; + seek(); + } + + public: + Range(const Range& other) + : ht(other.ht), i(other.i), count(other.count), prevp(&ht.ranges), next(ht.ranges) + { + *prevp = this; + if (next) + next->prevp = &next; + } + + ~Range() { + *prevp = next; + if (next) + next->prevp = prevp; + } + + private: + // Prohibit copy assignment. + Range& operator=(const Range& other) = delete; + + void seek() { + while (i < ht.dataLength && Ops::isEmpty(Ops::getKey(ht.data[i].element))) + i++; + } + + /* + * The hash table calls this when an entry is removed. + * j is the index of the removed entry. + */ + void onRemove(uint32_t j) { + MOZ_ASSERT(valid()); + if (j < i) + count--; + if (j == i) + seek(); + } + + /* + * The hash table calls this when the table is resized or compacted. + * Since |count| is the number of nonempty entries to the left of + * front(), discarding the empty entries will not affect count, and it + * will make i and count equal. + */ + void onCompact() { + MOZ_ASSERT(valid()); + i = count; + } + + /* The hash table calls this when cleared. */ + void onClear() { + MOZ_ASSERT(valid()); + i = count = 0; + } + + bool valid() const { + return next != this; + } + + void onTableDestroyed() { + MOZ_ASSERT(valid()); + prevp = &next; + next = this; + } + + public: + bool empty() const { + MOZ_ASSERT(valid()); + return i >= ht.dataLength; + } + + /* + * Return the first element in the range. This must not be called if + * this->empty(). + * + * Warning: Removing an entry from the table also removes it from any + * live Ranges, and a Range can become empty that way, rendering + * front() invalid. If in doubt, check empty() before calling front(). + */ + T& front() { + MOZ_ASSERT(valid()); + MOZ_ASSERT(!empty()); + return ht.data[i].element; + } + + /* + * Remove the first element from this range. + * This must not be called if this->empty(). + * + * Warning: Removing an entry from the table also removes it from any + * live Ranges, and a Range can become empty that way, rendering + * popFront() invalid. If in doubt, check empty() before calling + * popFront(). + */ + void popFront() { + MOZ_ASSERT(valid()); + MOZ_ASSERT(!empty()); + MOZ_ASSERT(!Ops::isEmpty(Ops::getKey(ht.data[i].element))); + count++; + i++; + seek(); + } + + /* + * Change the key of the front entry. + * + * This calls Ops::hash on both the current key and the new key. + * Ops::hash on the current key must return the same hash code as + * when the entry was added to the table. + */ + void rekeyFront(const Key& k) { + MOZ_ASSERT(valid()); + Data& entry = ht.data[i]; + HashNumber oldHash = prepareHash(Ops::getKey(entry.element)) >> ht.hashShift; + HashNumber newHash = prepareHash(k) >> ht.hashShift; + Ops::setKey(entry.element, k); + if (newHash != oldHash) { + // Remove this entry from its old hash chain. (If this crashes + // reading nullptr, it would mean we did not find this entry on + // the hash chain where we expected it. That probably means the + // key's hash code changed since it was inserted, breaking the + // hash code invariant.) + Data** ep = &ht.hashTable[oldHash]; + while (*ep != &entry) + ep = &(*ep)->chain; + *ep = entry.chain; + + // Add it to the new hash chain. We could just insert it at the + // beginning of the chain. Instead, we do a bit of work to + // preserve the invariant that hash chains always go in reverse + // insertion order (descending memory order). No code currently + // depends on this invariant, so it's fine to kill it if + // needed. + ep = &ht.hashTable[newHash]; + while (*ep && *ep > &entry) + ep = &(*ep)->chain; + entry.chain = *ep; + *ep = &entry; + } + } + }; + + Range all() { return Range(*this); } + + /* + * Change the value of the given key. + * + * This calls Ops::hash on both the current key and the new key. + * Ops::hash on the current key must return the same hash code as + * when the entry was added to the table. + */ + void rekeyOneEntry(const Key& current, const Key& newKey, const T& element) { + if (current == newKey) + return; + + Data* entry = lookup(current, prepareHash(current)); + if (!entry) + return; + + HashNumber oldHash = prepareHash(current) >> hashShift; + HashNumber newHash = prepareHash(newKey) >> hashShift; + + entry->element = element; + + // Remove this entry from its old hash chain. (If this crashes + // reading nullptr, it would mean we did not find this entry on + // the hash chain where we expected it. That probably means the + // key's hash code changed since it was inserted, breaking the + // hash code invariant.) + Data** ep = &hashTable[oldHash]; + while (*ep != entry) + ep = &(*ep)->chain; + *ep = entry->chain; + + // Add it to the new hash chain. We could just insert it at the + // beginning of the chain. Instead, we do a bit of work to + // preserve the invariant that hash chains always go in reverse + // insertion order (descending memory order). No code currently + // depends on this invariant, so it's fine to kill it if + // needed. + ep = &hashTable[newHash]; + while (*ep && *ep > entry) + ep = &(*ep)->chain; + entry->chain = *ep; + *ep = entry; + } + + private: + /* Logarithm base 2 of the number of buckets in the hash table initially. */ + static uint32_t initialBucketsLog2() { return 1; } + static uint32_t initialBuckets() { return 1 << initialBucketsLog2(); } + + /* + * The maximum load factor (mean number of entries per bucket). + * It is an invariant that + * dataCapacity == floor(hashBuckets() * fillFactor()). + * + * The fill factor should be between 2 and 4, and it should be chosen so that + * the fill factor times sizeof(Data) is close to but <= a power of 2. + * This fixed fill factor was chosen to make the size of the data + * array, in bytes, close to a power of two when sizeof(T) is 16. + */ + static double fillFactor() { return 8.0 / 3.0; } + + /* + * The minimum permitted value of (liveCount / dataLength). + * If that ratio drops below this value, we shrink the table. + */ + static double minDataFill() { return 0.25; } + + static HashNumber prepareHash(const Lookup& l) { + return ScrambleHashCode(Ops::hash(l)); + } + + /* The size of hashTable, in elements. Always a power of two. */ + uint32_t hashBuckets() const { + return 1 << (HashNumberSizeBits - hashShift); + } + + static void destroyData(Data* data, uint32_t length) { + for (Data* p = data + length; p != data; ) + (--p)->~Data(); + } + + void freeData(Data* data, uint32_t length) { + destroyData(data, length); + alloc.free_(data); + } + + Data* lookup(const Lookup& l, HashNumber h) { + for (Data* e = hashTable[h >> hashShift]; e; e = e->chain) { + if (Ops::match(Ops::getKey(e->element), l)) + return e; + } + return nullptr; + } + + const Data* lookup(const Lookup& l) const { + return const_cast(this)->lookup(l, prepareHash(l)); + } + + /* This is called after rehashing the table. */ + void compacted() { + // If we had any empty entries, compacting may have moved live entries + // to the left within |data|. Notify all live Ranges of the change. + for (Range* r = ranges; r; r = r->next) + r->onCompact(); + } + + /* Compact the entries in |data| and rehash them. */ + void rehashInPlace() { + for (uint32_t i = 0, N = hashBuckets(); i < N; i++) + hashTable[i] = nullptr; + Data* wp = data; + Data* end = data + dataLength; + for (Data* rp = data; rp != end; rp++) { + if (!Ops::isEmpty(Ops::getKey(rp->element))) { + HashNumber h = prepareHash(Ops::getKey(rp->element)) >> hashShift; + if (rp != wp) + wp->element = Move(rp->element); + wp->chain = hashTable[h]; + hashTable[h] = wp; + wp++; + } + } + MOZ_ASSERT(wp == data + liveCount); + + while (wp != end) + (--end)->~Data(); + dataLength = liveCount; + compacted(); + } + + /* + * Grow, shrink, or compact both |hashTable| and |data|. + * + * On success, this returns true, dataLength == liveCount, and there are no + * empty elements in data[0:dataLength]. On allocation failure, this + * leaves everything as it was and returns false. + */ + bool rehash(uint32_t newHashShift) { + // If the size of the table is not changing, rehash in place to avoid + // allocating memory. + if (newHashShift == hashShift) { + rehashInPlace(); + return true; + } + + size_t newHashBuckets = 1 << (HashNumberSizeBits - newHashShift); + Data** newHashTable = alloc.template pod_malloc(newHashBuckets); + if (!newHashTable) + return false; + for (uint32_t i = 0; i < newHashBuckets; i++) + newHashTable[i] = nullptr; + + uint32_t newCapacity = uint32_t(newHashBuckets * fillFactor()); + Data* newData = alloc.template pod_malloc(newCapacity); + if (!newData) { + alloc.free_(newHashTable); + return false; + } + + Data* wp = newData; + Data* end = data + dataLength; + for (Data* p = data; p != end; p++) { + if (!Ops::isEmpty(Ops::getKey(p->element))) { + HashNumber h = prepareHash(Ops::getKey(p->element)) >> newHashShift; + new (wp) Data(Move(p->element), newHashTable[h]); + newHashTable[h] = wp; + wp++; + } + } + MOZ_ASSERT(wp == newData + liveCount); + + alloc.free_(hashTable); + freeData(data, dataLength); + + hashTable = newHashTable; + data = newData; + dataLength = liveCount; + dataCapacity = newCapacity; + hashShift = newHashShift; + MOZ_ASSERT(hashBuckets() == newHashBuckets); + + compacted(); + return true; + } + + // Not copyable. + OrderedHashTable& operator=(const OrderedHashTable&) = delete; + OrderedHashTable(const OrderedHashTable&) = delete; +}; + +} // namespace detail + +template +class OrderedHashMap +{ + public: + class Entry + { + template friend class detail::OrderedHashTable; + void operator=(const Entry& rhs) { + const_cast(key) = rhs.key; + value = rhs.value; + } + + void operator=(Entry&& rhs) { + MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); + const_cast(key) = Move(rhs.key); + value = Move(rhs.value); + } + + public: + Entry() : key(), value() {} + Entry(const Key& k, const Value& v) : key(k), value(v) {} + Entry(Entry&& rhs) : key(Move(rhs.key)), value(Move(rhs.value)) {} + + const Key key; + Value value; + }; + + private: + struct MapOps : OrderedHashPolicy + { + typedef Key KeyType; + static void makeEmpty(Entry* e) { + OrderedHashPolicy::makeEmpty(const_cast(&e->key)); + + // Clear the value. Destroying it is another possibility, but that + // would complicate class Entry considerably. + e->value = Value(); + } + static const Key& getKey(const Entry& e) { return e.key; } + static void setKey(Entry& e, const Key& k) { const_cast(e.key) = k; } + }; + + typedef detail::OrderedHashTable Impl; + Impl impl; + + public: + typedef typename Impl::Range Range; + + explicit OrderedHashMap(AllocPolicy ap = AllocPolicy()) : impl(ap) {} + bool init() { return impl.init(); } + uint32_t count() const { return impl.count(); } + bool has(const Key& key) const { return impl.has(key); } + Range all() { return impl.all(); } + const Entry* get(const Key& key) const { return impl.get(key); } + Entry* get(const Key& key) { return impl.get(key); } + bool put(const Key& key, const Value& value) { return impl.put(Entry(key, value)); } + bool remove(const Key& key, bool* foundp) { return impl.remove(key, foundp); } + bool clear() { return impl.clear(); } + + void rekeyOneEntry(const Key& current, const Key& newKey) { + const Entry* e = get(current); + if (!e) + return; + return impl.rekeyOneEntry(current, newKey, Entry(newKey, e->value)); + } +}; + +template +class OrderedHashSet +{ + private: + struct SetOps : OrderedHashPolicy + { + typedef const T KeyType; + static const T& getKey(const T& v) { return v; } + static void setKey(const T& e, const T& v) { const_cast(e) = v; } + }; + + typedef detail::OrderedHashTable Impl; + Impl impl; + + public: + typedef typename Impl::Range Range; + + explicit OrderedHashSet(AllocPolicy ap = AllocPolicy()) : impl(ap) {} + bool init() { return impl.init(); } + uint32_t count() const { return impl.count(); } + bool has(const T& value) const { return impl.has(value); } + Range all() { return impl.all(); } + bool put(const T& value) { return impl.put(value); } + bool remove(const T& value, bool* foundp) { return impl.remove(value, foundp); } + bool clear() { return impl.clear(); } + + void rekeyOneEntry(const T& current, const T& newKey) { + return impl.rekeyOneEntry(current, newKey, newKey); + } +}; + +} // namespace js + +#endif /* ds_OrderedHashTable_h */ diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h index 46d3a678a6b..2b1243e065c 100644 --- a/js/src/gc/StoreBuffer.h +++ b/js/src/gc/StoreBuffer.h @@ -450,7 +450,7 @@ class StoreBuffer } - void assertHasValueEdge(Value* vp) { + void assertHasValueEdge(JS::Value* vp) { MOZ_ASSERT(bufferVal.has(this, ValueEdge(vp)) || !ValueEdge(vp).maybeInRememberedSet(nursery_)); } diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index 4a4aeb8e72e..ee24e65123b 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -24,6 +24,7 @@ #include "vm/Shape.h" #include "vm/Symbol.h" +#include "jscompartmentinlines.h" #include "jsgcinlines.h" #include "vm/ObjectGroup-inl.h" diff --git a/js/src/jit/BytecodeAnalysis.cpp b/js/src/jit/BytecodeAnalysis.cpp index 3fd0b0bd0ca..66e09417c02 100644 --- a/js/src/jit/BytecodeAnalysis.cpp +++ b/js/src/jit/BytecodeAnalysis.cpp @@ -9,6 +9,7 @@ #include "jsopcode.h" #include "jit/JitSpewer.h" #include "jsopcodeinlines.h" +#include "jsscriptinlines.h" using namespace js; using namespace js::jit; diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp index e7d44509a49..98d1ca8d257 100644 --- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -18,6 +18,7 @@ #include "jsobjinlines.h" #include "jsopcodeinlines.h" +#include "jsscriptinlines.h" using namespace js; using namespace js::jit; diff --git a/js/src/jit/IonCaches.h b/js/src/jit/IonCaches.h index f9b84ee5bcc..884604d33f3 100644 --- a/js/src/jit/IonCaches.h +++ b/js/src/jit/IonCaches.h @@ -14,6 +14,7 @@ #elif defined(JS_CODEGEN_MIPS) # include "jit/mips/Assembler-mips.h" #endif +#include "jit/JitCompartment.h" #include "jit/Registers.h" #include "jit/shared/Assembler-shared.h" #include "js/TrackedOptimizationInfo.h" diff --git a/js/src/jit/JitSpewer.cpp b/js/src/jit/JitSpewer.cpp index 4b064bf2be3..afce391b0a8 100644 --- a/js/src/jit/JitSpewer.cpp +++ b/js/src/jit/JitSpewer.cpp @@ -12,6 +12,7 @@ #include "jit/Ion.h" #include "jit/MIR.h" +#include "jit/MIRGenerator.h" #include "vm/HelperThreads.h" @@ -238,6 +239,15 @@ IonSpewer::~IonSpewer() release(); } +GraphSpewer::GraphSpewer(TempAllocator *alloc) + : graph_(nullptr), + c1Printer_(alloc->lifoAlloc()), + jsonPrinter_(alloc->lifoAlloc()), + c1Spewer_(c1Printer_), + jsonSpewer_(jsonPrinter_) +{ +} + void GraphSpewer::init(MIRGraph* graph, JSScript* function) { diff --git a/js/src/jit/JitSpewer.h b/js/src/jit/JitSpewer.h index 5516e4ef411..83fb8b6718e 100644 --- a/js/src/jit/JitSpewer.h +++ b/js/src/jit/JitSpewer.h @@ -116,13 +116,7 @@ class GraphSpewer JSONSpewer jsonSpewer_; public: - explicit GraphSpewer(TempAllocator *alloc) - : graph_(nullptr), - c1Printer_(alloc->lifoAlloc()), - jsonPrinter_(alloc->lifoAlloc()), - c1Spewer_(c1Printer_), - jsonSpewer_(jsonPrinter_) - { } + explicit GraphSpewer(TempAllocator *alloc); bool isSpewing() const { return graph_; diff --git a/js/src/jit/JitcodeMap.cpp b/js/src/jit/JitcodeMap.cpp index 3a4f1cf2a2a..a386423df50 100644 --- a/js/src/jit/JitcodeMap.cpp +++ b/js/src/jit/JitcodeMap.cpp @@ -8,23 +8,26 @@ #include "mozilla/DebugOnly.h" #include "mozilla/MathAlgorithms.h" +#include "mozilla/Maybe.h" #include "mozilla/SizePrintfMacros.h" #include "mozilla/UniquePtr.h" + #include "jsprf.h" + #include "gc/Marking.h" #include "gc/Statistics.h" - #include "jit/BaselineJIT.h" #include "jit/JitSpewer.h" - #include "js/Vector.h" #include "vm/SPSProfiler.h" + #include "jsscriptinlines.h" +using mozilla::Maybe; + namespace js { namespace jit { - static inline JitcodeRegionEntry RegionAtAddr(const JitcodeGlobalEntry::IonEntry& entry, void* ptr, uint32_t* ptrOffset) @@ -1052,7 +1055,7 @@ JitcodeGlobalEntry::IonCacheEntry::forEachOptimizationAttempt( entry.forEachOptimizationAttempt(rt, index, op); // Record the outcome associated with the stub. - op(TrackedStrategy::InlineCache_OptimizedStub, trackedOutcome_); + op(JS::TrackedStrategy::InlineCache_OptimizedStub, trackedOutcome_); } void diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 01c15a08f81..56673fa8fc2 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -25,6 +25,7 @@ #include "jsatominlines.h" #include "jsobjinlines.h" +#include "jsscriptinlines.h" #include "jit/AtomicOperations-inl.h" diff --git a/js/src/jit/ScalarReplacement.cpp b/js/src/jit/ScalarReplacement.cpp index 7667be405aa..9aa9021eeca 100644 --- a/js/src/jit/ScalarReplacement.cpp +++ b/js/src/jit/ScalarReplacement.cpp @@ -15,6 +15,8 @@ #include "jit/MIRGraph.h" #include "vm/UnboxedObject.h" +#include "jsobjinlines.h" + namespace js { namespace jit { diff --git a/js/src/jit/x64/Trampoline-x64.cpp b/js/src/jit/x64/Trampoline-x64.cpp index 3a45a5a8c97..a15a871c5f4 100644 --- a/js/src/jit/x64/Trampoline-x64.cpp +++ b/js/src/jit/x64/Trampoline-x64.cpp @@ -14,6 +14,8 @@ #include "jit/VMFunctions.h" #include "jit/x64/SharedICHelpers-x64.h" +#include "jit/MacroAssembler-inl.h" + using namespace js; using namespace js::jit; diff --git a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h index 7030780bc5a..0b07ab39369 100644 --- a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h +++ b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h @@ -3824,6 +3824,13 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off // Linking & patching: + void assertValidJmpSrc(JmpSrc src) + { + // The target offset is stored at offset - 4. + MOZ_ASSERT(src.offset() > int32_t(sizeof(int32_t))); + MOZ_ASSERT(size_t(src.offset()) <= size()); + } + bool nextJump(const JmpSrc& from, JmpSrc* next) { // Sanity check - if the assembler has OOM'd, it will start overwriting @@ -3831,10 +3838,14 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off if (oom()) return false; + assertValidJmpSrc(from); + const unsigned char* code = m_formatter.data(); int32_t offset = GetInt32(code + from.offset()); if (offset == -1) return false; + + MOZ_ASSERT(size_t(offset) < size()); *next = JmpSrc(offset); return true; } @@ -3845,6 +3856,9 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off if (oom()) return; + assertValidJmpSrc(from); + MOZ_ASSERT(to.offset() == -1 || size_t(to.offset()) <= size()); + unsigned char* code = m_formatter.data(); SetInt32(code + from.offset(), to.offset()); } @@ -3859,6 +3873,9 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off if (oom()) return; + assertValidJmpSrc(from); + MOZ_ASSERT(size_t(to.offset()) <= size()); + spew(".set .Lfrom%d, .Llabel%d", from.offset(), to.offset()); unsigned char* code = m_formatter.data(); SetRel32(code + from.offset(), code + to.offset()); diff --git a/js/src/vm/Printer.h b/js/src/vm/Printer.h index ef759d283cf..29763a39620 100644 --- a/js/src/vm/Printer.h +++ b/js/src/vm/Printer.h @@ -8,6 +8,7 @@ #define vm_Printer_h #include +#include #include class JSString; diff --git a/js/src/vm/ReceiverGuard.cpp b/js/src/vm/ReceiverGuard.cpp index 81b36ce387e..d491c5e44eb 100644 --- a/js/src/vm/ReceiverGuard.cpp +++ b/js/src/vm/ReceiverGuard.cpp @@ -8,6 +8,7 @@ #include "builtin/TypedObject.h" #include "vm/UnboxedObject.h" +#include "jsobjinlines.h" using namespace js; diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index f16f684925c..045988665e3 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -20,6 +20,7 @@ #include "js/HashTable.h" #include "jscntxtinlines.h" +#include "jscompartmentinlines.h" #include "jsobjinlines.h" #include "vm/NativeObject-inl.h" diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp index 38d11bdff38..abfce4844af 100644 --- a/js/src/vm/UnboxedObject.cpp +++ b/js/src/vm/UnboxedObject.cpp @@ -338,7 +338,7 @@ UnboxedPlainObject::ensureExpando(JSContext* cx, Handle obj return obj->expando_; UnboxedExpandoObject* expando = - NewObjectWithGivenProto(cx, nullptr, AllocKind::OBJECT4); + NewObjectWithGivenProto(cx, nullptr, gc::AllocKind::OBJECT4); if (!expando) return nullptr; diff --git a/js/xpconnect/src/XPCWrappedNativeInfo.cpp b/js/xpconnect/src/XPCWrappedNativeInfo.cpp index 48816435fae..ee8aeb60efe 100644 --- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp +++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp @@ -239,8 +239,8 @@ XPCNativeInterface::NewInstance(nsIInterfaceInfo* aInfo) if (mainProcessScriptableOnly && !XRE_IsParentProcess()) { nsCOMPtr console(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); if (console) { - char* intfNameChars; - aInfo->GetName(&intfNameChars); + const char* intfNameChars; + aInfo->GetNameShared(&intfNameChars); nsPrintfCString errorMsg("Use of %s in content process is deprecated.", intfNameChars); nsAutoString filename; diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 411a1b877f1..9ca42f6662b 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -1470,7 +1470,8 @@ RestyleManager::RestyleForRemove(Element* aContainer, // This should be an assert, but this is called incorrectly in // nsHTMLEditor::DeleteRefToAnonymousNode and the assertions were clogging // up the logs. Make it an assert again when that's fixed. - NS_WARNING("anonymous nodes should not be in child lists (bug 439258)"); + MOZ_ASSERT(aOldChild->GetProperty(nsGkAtoms::restylableAnonymousNode), + "anonymous nodes should not be in child lists (bug 439258)"); } uint32_t selectorFlags = aContainer ? (aContainer->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0; diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index eaa04ce71e4..ebabe547b68 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -231,6 +231,7 @@ CommonAnimationManager::RulesMatching(ElementRuleProcessorData* aData) nsCSSPseudoElements::ePseudo_NotPseudoElement); if (rule) { aData->mRuleWalker->Forward(rule); + aData->mRuleWalker->CurrentNode()->SetIsAnimationRule(); } } @@ -250,6 +251,7 @@ CommonAnimationManager::RulesMatching(PseudoElementRuleProcessorData* aData) nsIStyleRule *rule = GetAnimationRule(aData->mElement, aData->mPseudoType); if (rule) { aData->mRuleWalker->Forward(rule); + aData->mRuleWalker->CurrentNode()->SetIsAnimationRule(); } } @@ -486,6 +488,15 @@ AnimValuesStyleRule::MapRuleInfoInto(nsRuleData* aRuleData) // Don't apply transitions or animations to things inside of // pseudo-elements. // FIXME (Bug 522599): Add tests for this. + + // Prevent structs from being cached on the rule node since we're inside + // a pseudo-element, as we could determine cacheability differently + // when walking the rule tree for a style context that is not inside + // a pseudo-element. Note that nsRuleNode::GetStyle##name_ and GetStyleData + // will never look at cached structs when we're animating things inside + // a pseduo-element, so that we don't incorrectly return a struct that + // is only appropriate for non-pseudo-elements. + aRuleData->mConditions.SetUncacheable(); return; } diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index d03564b1f65..5aa95d89645 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -1475,7 +1475,8 @@ nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent, mNextSibling(nullptr), mDependentBits((uint32_t(aLevel) << NS_RULE_NODE_LEVEL_SHIFT) | (aIsImportant ? NS_RULE_NODE_IS_IMPORTANT : 0)), - mNoneBits(0), + mNoneBits(aParent ? aParent->mNoneBits & NS_RULE_NODE_HAS_ANIMATION_DATA : + 0), mRefCnt(0) { MOZ_ASSERT(aContext); @@ -9321,9 +9322,14 @@ nsRuleNode::GetStyleData(nsStyleStructID aSID, "in some way."); const void *data; - data = mStyleData.GetStyleData(aSID, aContext); - if (MOZ_LIKELY(data != nullptr)) - return data; // We have a fully specified struct. Just return it. + + // Never use cached data for animated style inside a pseudo-element; + // see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto. + if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) { + data = mStyleData.GetStyleData(aSID, aContext); + if (MOZ_LIKELY(data != nullptr)) + return data; // We have a fully specified struct. Just return it. + } if (MOZ_UNLIKELY(!aComputeData)) return nullptr; @@ -9779,3 +9785,10 @@ nsRuleNode::ComputeColor(const nsCSSValue& aValue, nsPresContext* aPresContext, MOZ_ASSERT(ok || !(aPresContext && aStyleContext)); return ok; } + +/* static */ bool +nsRuleNode::ParentHasPseudoElementData(nsStyleContext* aContext) +{ + nsStyleContext* parent = aContext->GetParent(); + return parent && parent->HasPseudoElementData(); +} diff --git a/layout/style/nsRuleNode.h b/layout/style/nsRuleNode.h index 854719adb9f..1fbc49553bc 100644 --- a/layout/style/nsRuleNode.h +++ b/layout/style/nsRuleNode.h @@ -843,6 +843,29 @@ public: return (mDependentBits & NS_RULE_NODE_USED_DIRECTLY) != 0; } + /** + * Is the mRule of this rule node an AnimValuesStyleRule? + */ + void SetIsAnimationRule() { + MOZ_ASSERT(!HaveChildren() || + (mDependentBits & NS_RULE_NODE_IS_ANIMATION_RULE), + "SetIsAnimationRule must only set the IS_ANIMATION_RULE bit " + "before the rule node has children"); + mDependentBits |= NS_RULE_NODE_IS_ANIMATION_RULE; + mNoneBits |= NS_RULE_NODE_HAS_ANIMATION_DATA; + } + bool IsAnimationRule() const { + return (mDependentBits & NS_RULE_NODE_IS_ANIMATION_RULE) != 0; + } + + /** + * Is the mRule of this rule node or any of its ancestors an + * AnimValuesStyleRule? + */ + bool HasAnimationData() const { + return (mNoneBits & NS_RULE_NODE_HAS_ANIMATION_DATA) != 0; + } + // NOTE: Does not |AddRef|. Null only for the root. nsIStyleRule* GetRule() const { return mRule; } // NOTE: Does not |AddRef|. Never null. @@ -866,9 +889,14 @@ public: "in some way."); \ \ const nsStyle##name_ *data; \ - data = mStyleData.GetStyle##name_(); \ - if (MOZ_LIKELY(data != nullptr)) \ - return data; \ + \ + /* Never use cached data for animated style inside a pseudo-element; */ \ + /* see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto */ \ + if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) { \ + data = mStyleData.GetStyle##name_(); \ + if (MOZ_LIKELY(data != nullptr)) \ + return data; \ + } \ \ if (!aComputeData) \ return nullptr; \ @@ -891,9 +919,14 @@ public: "in some way."); \ \ const nsStyle##name_ *data; \ - data = mStyleData.GetStyle##name_(aContext); \ - if (MOZ_LIKELY(data != nullptr)) \ - return data; \ + \ + /* Never use cached data for animated style inside a pseudo-element; */ \ + /* see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto */ \ + if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) { \ + data = mStyleData.GetStyle##name_(aContext); \ + if (MOZ_LIKELY(data != nullptr)) \ + return data; \ + } \ \ if (!aComputeData) \ return nullptr; \ @@ -1017,6 +1050,8 @@ public: nsPresContext* aPresContext, nsStyleContext* aStyleContext, nscolor& aResult); + + static bool ParentHasPseudoElementData(nsStyleContext* aContext); }; #endif diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index b7932c19346..422e50ad017 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -845,6 +845,7 @@ ReplaceAnimationRule(nsRuleNode *aOldRuleNode, if (aNewAnimRule) { n = n->Transition(aNewAnimRule, nsStyleSet::eAnimationSheet, false); + n->SetIsAnimationRule(); } for (uint32_t i = moreSpecificNodes.Length(); i-- != 0; ) { @@ -1439,6 +1440,7 @@ struct RuleNodeInfo { nsIStyleRule* mRule; uint8_t mLevel; bool mIsImportant; + bool mIsAnimationRule; }; struct CascadeLevel { @@ -1508,6 +1510,7 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, curRule->mRule = ruleNode->GetRule(); curRule->mLevel = ruleNode->GetLevel(); curRule->mIsImportant = ruleNode->IsImportantRule(); + curRule->mIsAnimationRule = ruleNode->IsAnimationRule(); } nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled); @@ -1538,6 +1541,7 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, GetAnimationRule(aElement, aPseudoType); if (rule) { ruleWalker.ForwardOnPossiblyCSSRule(rule); + ruleWalker.CurrentNode()->SetIsAnimationRule(); } } break; @@ -1550,6 +1554,7 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, GetAnimationRule(aElement, aPseudoType); if (rule) { ruleWalker.ForwardOnPossiblyCSSRule(rule); + ruleWalker.CurrentNode()->SetIsAnimationRule(); } } break; @@ -1615,6 +1620,9 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, if (!doReplace) { ruleWalker.ForwardOnPossiblyCSSRule(ruleInfo.mRule); + if (ruleInfo.mIsAnimationRule) { + ruleWalker.CurrentNode()->SetIsAnimationRule(); + } } } } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index c5c0e6c4d7a..15e59f13ae2 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -67,12 +67,16 @@ class imgIContainer; #define NS_STYLE_CONTEXT_TYPE_SHIFT 34 // Additional bits for nsRuleNode's mDependentBits: +#define NS_RULE_NODE_IS_ANIMATION_RULE 0x01000000 #define NS_RULE_NODE_GC_MARK 0x02000000 #define NS_RULE_NODE_USED_DIRECTLY 0x04000000 #define NS_RULE_NODE_IS_IMPORTANT 0x08000000 #define NS_RULE_NODE_LEVEL_MASK 0xf0000000 #define NS_RULE_NODE_LEVEL_SHIFT 28 +// Additional bits for nsRuleNode's mNoneBits: +#define NS_RULE_NODE_HAS_ANIMATION_DATA 0x80000000 + // The lifetime of these objects is managed by the presshell's arena. struct nsStyleFont { diff --git a/layout/style/test/test_logical_properties.html b/layout/style/test/test_logical_properties.html index 842b638021e..3b3dbf415f2 100644 --- a/layout/style/test/test_logical_properties.html +++ b/layout/style/test/test_logical_properties.html @@ -5,7 +5,12 @@ -
+ + + +
+ + diff --git a/testing/web-platform/tests/FileAPI/idlharness.idl b/testing/web-platform/tests/FileAPI/idlharness.idl new file mode 100644 index 00000000000..ae83a9cb1fd --- /dev/null +++ b/testing/web-platform/tests/FileAPI/idlharness.idl @@ -0,0 +1,81 @@ +[Constructor, + Constructor(sequence<(ArrayBuffer or ArrayBufferView or Blob or DOMString)> blobParts, optional BlobPropertyBag options), Exposed=Window,Worker] +interface Blob { + + readonly attribute unsigned long long size; + readonly attribute DOMString type; + readonly attribute boolean isClosed; + + //slice Blob into byte-ranged chunks + + Blob slice([Clamp] optional long long start, + [Clamp] optional long long end, + optional DOMString contentType); + void close(); + +}; + +dictionary BlobPropertyBag { + DOMString type = ""; +}; + +[Constructor(sequence<(Blob or DOMString or ArrayBufferView or ArrayBuffer)> fileBits, +[EnsureUTF16] DOMString fileName, optional FilePropertyBag options), Exposed=Window,Worker] +interface File : Blob { + + readonly attribute DOMString name; + readonly attribute long long lastModified; + +}; + +dictionary FilePropertyBag { + + DOMString type = ""; + long long lastModified; + +}; + +[Exposed=Window,Worker] interface FileList { + getter File? item(unsigned long index); + readonly attribute unsigned long length; +}; + +[Constructor, Exposed=Window,Worker] +interface FileReader: EventTarget { + + // async read methods + void readAsArrayBuffer(Blob blob); + void readAsText(Blob blob, optional DOMString label); + void readAsDataURL(Blob blob); + + void abort(); + + // states + const unsigned short EMPTY = 0; + const unsigned short LOADING = 1; + const unsigned short DONE = 2; + + readonly attribute unsigned short readyState; + + // File or Blob data + readonly attribute (DOMString or ArrayBuffer)? result; + + readonly attribute DOMError? error; + + // event handler attributes + attribute EventHandler onloadstart; + attribute EventHandler onprogress; + attribute EventHandler onload; + attribute EventHandler onabort; + attribute EventHandler onerror; + attribute EventHandler onloadend; + +}; + +partial interface URL { + + static DOMString createObjectURL(Blob blob); + static DOMString createFor(Blob blob); + static void revokeObjectURL(DOMString url); + +}; diff --git a/testing/web-platform/tests/FileAPI/idlharness.worker.js b/testing/web-platform/tests/FileAPI/idlharness.worker.js new file mode 100644 index 00000000000..40ba81699b0 --- /dev/null +++ b/testing/web-platform/tests/FileAPI/idlharness.worker.js @@ -0,0 +1,45 @@ +importScripts("/resources/testharness.js"); +importScripts("/resources/WebIDLParser.js", "/resources/idlharness.js"); + +var request = new XMLHttpRequest(); +request.open("GET", "idlharness.idl"); +request.send(); +request.onload = function() { + var idl_array = new IdlArray(); + var idls = request.responseText; + + idl_array.add_untested_idls("[Global] interface Window { };"); + + idl_array.add_untested_idls("interface ArrayBuffer {};"); + idl_array.add_untested_idls("interface ArrayBufferView {};"); + idl_array.add_untested_idls("interface URL {};"); + idl_array.add_untested_idls("interface EventTarget {};"); + idl_array.add_untested_idls("interface Event {};"); + idl_array.add_untested_idls("[TreatNonCallableAsNull] callback EventHandlerNonNull = any (Event event);"); + idl_array.add_untested_idls("typedef EventHandlerNonNull? EventHandler;"); + + + var worker_idls = + '[Constructor, Exposed=Worker]\n' + + 'interface FileReaderSync {\n' + + '\n' + + ' // Synchronously return strings\n' + + '\n' + + ' ArrayBuffer readAsArrayBuffer(Blob blob);\n' + + ' DOMString readAsText(Blob blob, optional DOMString label);\n' + + ' DOMString readAsDataURL(Blob blob);\n' + + '};'; + + idl_array.add_idls(idls); + idl_array.add_idls(worker_idls); + + idl_array.add_objects({ + Blob: ['new Blob(["TEST"])'], + File: ['new File(["myFileBits"], "myFileName")'], + FileReader: ['new FileReader()'], + FileReaderSync: ['new FileReaderSync()'] + }); + + idl_array.test(); + done(); +}; diff --git a/testing/web-platform/tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constructor.html b/testing/web-platform/tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constructor.html index 9dc6d9918a3..0e5ffea7d32 100644 --- a/testing/web-platform/tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constructor.html +++ b/testing/web-platform/tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constructor.html @@ -24,6 +24,14 @@ test(function() { "The message property should be inherited"); }, 'new DOMException(): own-ness'); +test(function() { + var ex = new DOMException(null); + assert_equals(ex.name, "Error", + "Not passing a name should end up with 'Error' as the name"); + assert_equals(ex.message, "null", + "Passing null as message should end up with stringified 'null' as the message"); +}, 'new DOMException(null)'); + test(function() { var ex = new DOMException(undefined); assert_equals(ex.name, "Error", @@ -55,6 +63,13 @@ test(function() { "The message property should be own"); }, 'new DOMException("foo"): own-ness'); +test(function() { + var ex = new DOMException("bar", undefined); + assert_equals(ex.name, "Error", + "Passing undefined for name should end up with 'Error' as the name"); + assert_equals(ex.message, "bar", "Should still be using passed-in message"); +}, 'new DOMException("bar", undefined)'); + test(function() { var ex = new DOMException("bar", "NotSupportedError"); assert_equals(ex.name, "NotSupportedError", "Should be using the passed-in name"); @@ -70,4 +85,55 @@ test(function() { assert_true(ex.hasOwnProperty("message"), "The message property should be own"); }, 'new DOMException("bar", "NotSupportedError"): own-ness'); + +test(function() { + var ex = new DOMException("bar", "foo"); + assert_equals(ex.name, "foo", "Should be using the passed-in name"); + assert_equals(ex.message, "bar", "Should still be using passed-in message"); + assert_equals(ex.code, 0, + "Should have 0 for code for a name not in the exception names table"); +}, 'new DOMException("bar", "foo")'); + +[ + {name: "IndexSizeError", code: 1}, + {name: "HierarchyRequestError", code: 3}, + {name: "WrongDocumentError", code: 4}, + {name: "InvalidCharacterError", code: 5}, + {name: "NoModificationAllowedError", code: 7}, + {name: "NotFoundError", code: 8}, + {name: "NotSupportedError", code: 9}, + {name: "InUseAttributeError", code: 10}, + {name: "InvalidStateError", code: 11}, + {name: "SyntaxError", code: 12}, + {name: "InvalidModificationError", code: 13}, + {name: "NamespaceError", code: 14}, + {name: "InvalidAccessError", code: 15}, + {name: "SecurityError", code: 18}, + {name: "NetworkError", code: 19}, + {name: "AbortError", code: 20}, + {name: "URLMismatchError", code: 21}, + {name: "QuotaExceededError", code: 22}, + {name: "TimeoutError", code: 23}, + {name: "InvalidNodeTypeError", code: 24}, + {name: "DataCloneError", code: 25} +].forEach(function(test_case) { + test(function() { + var ex = new DOMException("msg", test_case.name); + assert_equals(ex.name, test_case.name, + "Should be using the passed-in name"); + assert_equals(ex.message, "msg", + "Should be using the passed-in message"); + assert_equals(ex.code, test_case.code, + "Should have matching legacy code from error names table"); + },'new DOMexception("msg", "' + test_case.name + '")'); +}); + +test(function() { + var ex = new DOMException("bar", "UnknownError"); + assert_equals(ex.name, "UnknownError", "Should be using the passed-in name"); + assert_equals(ex.message, "bar", "Should still be using passed-in message"); + assert_equals(ex.code, 0, + "Should have 0 for code for a name in the exception names table with no legacy code"); +}, 'new DOMException("bar", "UnknownError")'); + diff --git a/testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/571.html b/testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/571-haswarn.html similarity index 100% rename from testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/571.html rename to testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/571-haswarn.html diff --git a/testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/572.html b/testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/572-haswarn.html similarity index 100% rename from testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/572.html rename to testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/572-haswarn.html diff --git a/testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/573.html b/testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/573-haswarn.html similarity index 100% rename from testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/573.html rename to testing/web-platform/tests/conformance-checkers/html-aria/author-requirements/573-haswarn.html diff --git a/testing/web-platform/tests/conformance-checkers/html-aria/combobox-autocomplete-list/div.html b/testing/web-platform/tests/conformance-checkers/html-aria/combobox-autocomplete-list/div-haswarn.html similarity index 100% rename from testing/web-platform/tests/conformance-checkers/html-aria/combobox-autocomplete-list/div.html rename to testing/web-platform/tests/conformance-checkers/html-aria/combobox-autocomplete-list/div-haswarn.html diff --git a/testing/web-platform/tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-disparity.html b/testing/web-platform/tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-disparity-haswarn.html similarity index 100% rename from testing/web-platform/tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-disparity.html rename to testing/web-platform/tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-disparity-haswarn.html diff --git a/testing/web-platform/tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-role.html b/testing/web-platform/tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-role-haswarn.html similarity index 100% rename from testing/web-platform/tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-role.html rename to testing/web-platform/tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-role-haswarn.html diff --git a/testing/web-platform/tests/conformance-checkers/messages.json b/testing/web-platform/tests/conformance-checkers/messages.json index 34990c02200..1b5daba1f65 100644 --- a/testing/web-platform/tests/conformance-checkers/messages.json +++ b/testing/web-platform/tests/conformance-checkers/messages.json @@ -1,4 +1,10 @@ { + "html-aria/author-requirements/571-haswarn.html": "The \u201ctextbox\u201d role is unnecessary for an \u201cinput\u201d element that has no \u201clist\u201d attribute and whose type is \u201ctext\u201d.", + "html-aria/author-requirements/572-haswarn.html": "The \u201ctextbox\u201d role is unnecessary for an \u201cinput\u201d element that has no \u201clist\u201d attribute and whose type is \u201ctext\u201d.", + "html-aria/author-requirements/573-haswarn.html": "The \u201ctextbox\u201d role is unnecessary for an \u201cinput\u201d element that has no \u201clist\u201d attribute and whose type is \u201ctext\u201d.", + "html-aria/combobox-autocomplete-list/div-haswarn.html": "The \u201ctextbox\u201d role is unnecessary for an \u201cinput\u201d element that has no \u201clist\u201d attribute and whose type is \u201ctext\u201d.", + "html-aria/host-language/implicit-semantics-checkbox-disparity-haswarn.html": "The \u201ccheckbox\u201d role is unnecessary for element \u201cinput\u201d whose type is \u201ccheckbox\u201d.", + "html-aria/host-language/implicit-semantics-checkbox-role-haswarn.html": "The \u201ccheckbox\u201d role is unnecessary for element \u201cinput\u201d whose type is \u201ccheckbox\u201d.", "html-rdfa/0019-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cdiv\u201d in this context.", "html-rdfa/0035-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cimg\u201d in this context.", "html-rdfa/0037-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cimg\u201d in this context.", diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/alert-pass.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/alert-pass.js deleted file mode 100644 index ec2f0076d57..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/alert-pass.js +++ /dev/null @@ -1 +0,0 @@ -alert_assert('PASS'); diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/child-src-test.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/child-src-test.js deleted file mode 100644 index fd09f153716..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/child-src-test.js +++ /dev/null @@ -1,66 +0,0 @@ -var EXPECT_BLOCK = true; -var EXPECT_LOAD = false; - -window.jsTestIsAsync = true; -window.wasPostTestScriptParsed = true; - -var iframe; - -function injectFrame(url, shouldBlock) { - window.onload = function() { - iframe = document.createElement('iframe'); - iframe.onload = iframeLoaded(shouldBlock); - iframe.src = url; - document.body.appendChild(iframe); - }; -} - -function iframeLoaded(expectBlock) { - return function(ev) { - var failed = true; - try { - console.log("IFrame load event fired: the IFrame's location is '" + ev.target.contentWindow.location.href + "'."); - if (expectBlock) { - testFailed("The IFrame should have been blocked (or cross-origin). It wasn't."); - failed = true; - } else { - testPassed("The IFrame should not have been blocked. It wasn't."); - failed = false; - } - } catch (ex) { - debug("IFrame load event fired: the IFrame is cross-origin (or was blocked)."); - if (expectBlock) { - testPassed("The IFrame should have been blocked (or cross-origin). It was."); - failed = false; - } else { - testFailed("The IFrame should not have been blocked. It was."); - failed = true; - } - } - finishJSTest(); - }; -} - -function injectFrameRedirectingTo(url, shouldBlock) { - injectFrame("/security/contentSecurityPolicy/resources/redir.php?url=" + url, shouldBlock); -} - -function injectWorker(url, expectBlock) { - window.onload = function() { - if (expectBlock == EXPECT_BLOCK) - shouldThrow("var w = new Worker('" + url + "');"); - else - shouldNotThrow("var w = new Worker('" + url + "');"); - finishJSTest(); - }; -} - -function injectSharedWorker(url, expectBlock) { - window.onload = function() { - if (expectBlock == EXPECT_BLOCK) - shouldThrow("var w = new SharedWorker('" + url + "');"); - else - shouldNotThrow("var w = new SharedWorker('" + url + "');"); - finishJSTest(); - }; -} diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/dump-as-text.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/dump-as-text.js deleted file mode 100644 index a229b1fc75c..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/dump-as-text.js +++ /dev/null @@ -1,2 +0,0 @@ -if (window.testRunner) - testRunner.dumpAsText(); diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/frame-ancestors-test.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/frame-ancestors-test.js deleted file mode 100644 index e4b12d4faf7..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/frame-ancestors-test.js +++ /dev/null @@ -1,109 +0,0 @@ -var SAME_ORIGIN = true; -var CROSS_ORIGIN = false; - -var EXPECT_BLOCK = true; -var EXPECT_LOAD = false; - -var SAMEORIGIN_ORIGIN = "http://127.0.0.1:8000"; -var CROSSORIGIN_ORIGIN = "http://localhost:8080"; - -window.jsTestIsAsync = true; -window.wasPostTestScriptParsed = true; - -if (window.testRunner) - testRunner.dumpChildFramesAsText(); - -window.addEventListener("message", function(e) { - if (window.parent != window) { - window.parent.postMessage(e.data, "*"); - } else { - if (e.data) - testFailed("The inner IFrame failed."); - else - testPassed("The inner IFrame passed."); - - finishJSTest(); - } -}); - -function injectNestedIframe(policy, parent, child, expectation) { - var iframe = document.createElement("iframe"); - - var url = "/security/contentSecurityPolicy/resources/frame-in-frame.pl?" + "policy=" + policy + "&parent=" + parent + "&child=" + child + "&expectation=" + expectation; - url = (parent == "same" ? SAMEORIGIN_ORIGIN : CROSSORIGIN_ORIGIN) + url; - - iframe.src = url; - document.body.appendChild(iframe); -} - -function injectIFrame(policy, sameOrigin, expectBlock) { - var iframe = document.createElement("iframe"); - iframe.addEventListener("load", iframeLoaded(expectBlock)); - iframe.addEventListener("error", iframeLoaded(expectBlock)); - - var url = "/security/contentSecurityPolicy/resources/frame-ancestors.pl?policy=" + policy; - if (!sameOrigin) - url = CROSSORIGIN_ORIGIN + url; - - iframe.src = url; - document.body.appendChild(iframe); -} - -function iframeLoaded(expectBlock) { - return function(ev) { - var failed = true; - try { - console.log("IFrame load event fired: the IFrame's location is '" + ev.target.contentWindow.location.href + "'."); - if (expectBlock) { - testFailed("The IFrame should have been blocked (or cross-origin). It wasn't."); - failed = true; - } else { - testPassed("The IFrame should not have been blocked. It wasn't."); - failed = false; - } - } catch (ex) { - debug("IFrame load event fired: the IFrame is cross-origin (or was blocked)."); - if (expectBlock) { - testPassed("The IFrame should have been blocked (or cross-origin). It was."); - failed = false; - } else { - testFailed("The IFrame should not have been blocked. It was."); - failed = true; - } - } - if (window.parent != window) - window.parent.postMessage(failed, '*'); - else - finishJSTest(); - }; -} - -function crossOriginFrameShouldBeBlocked(policy) { - window.onload = function() { - injectIFrame(policy, CROSS_ORIGIN, EXPECT_BLOCK); - }; -} - -function crossOriginFrameShouldBeAllowed(policy) { - window.onload = function() { - injectIFrame(policy, CROSS_ORIGIN, EXPECT_LOAD); - }; -} - -function sameOriginFrameShouldBeBlocked(policy) { - window.onload = function() { - injectIFrame(policy, SAME_ORIGIN, EXPECT_BLOCK); - }; -} - -function sameOriginFrameShouldBeAllowed(policy) { - window.onload = function() { - injectIFrame(policy, SAME_ORIGIN, EXPECT_LOAD); - }; -} - -function testNestedIFrame(policy, parent, child, expectation) { - window.onload = function() { - injectNestedIframe(policy, parent == SAME_ORIGIN ? "same" : "cross", child == SAME_ORIGIN ? "same" : "cross", expectation == EXPECT_LOAD ? "Allowed" : "Blocked"); - }; -} diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/mixed-content-with-csp.html b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/mixed-content-with-csp.html deleted file mode 100644 index 77f47cf3b1c..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/mixed-content-with-csp.html +++ /dev/null @@ -1,2 +0,0 @@ - This page includes an insecure script that alerts "FAIL", but that script is blocked by CSP. - diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/multiple-iframe-plugin-test.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/multiple-iframe-plugin-test.js deleted file mode 100644 index 0a6f0c5e1be..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/multiple-iframe-plugin-test.js +++ /dev/null @@ -1,54 +0,0 @@ -if (window.testRunner) { - testRunner.waitUntilDone(); - testRunner.dumpAsText(); - testRunner.dumpChildFramesAsText(); -} - -function testExperimentalPolicy() { - testImpl(true); -} - -function test() { - testImpl(false); -} - -function testImpl(experimental) { - if (tests.length === 0) - return finishTesting(); - var baseURL = "/security/contentSecurityPolicy/"; - var current = tests.shift(); - var iframe = document.createElement("iframe"); - iframe.src = baseURL + "resources/echo-object-data.pl?" + - "experimental=" + (experimental ? "true" : "false") + - "&csp=" + escape(current[1]); - - if (current[0]) - iframe.src += "&log=PASS."; - else - iframe.src += "&log=FAIL."; - - if (current[2]) - iframe.src += "&plugin=" + escape(current[2]); - else { - iframe.src += "&plugin=data:application/x-webkit-test-netscape,logifloaded"; - } - - if (current[3] !== undefined) - iframe.src += "&type=" + escape(current[3]); - else - iframe.src += "&type=application/x-webkit-test-netscape"; - - iframe.onload = function() { - if (window.internals) - internals.updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(iframe); - testImpl(experimental); - }; - document.body.appendChild(iframe); -} - -function finishTesting() { - if (window.testRunner) { - setTimeout("testRunner.notifyDone()", 0); - } - return true; -} diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/multiple-iframe-test.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/multiple-iframe-test.js deleted file mode 100644 index d5139dcd87a..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/multiple-iframe-test.js +++ /dev/null @@ -1,53 +0,0 @@ -if (window.testRunner) { - testRunner.waitUntilDone(); - testRunner.dumpAsText(); - testRunner.dumpChildFramesAsText(); -} - -function testPreescapedPolicy() { - testImpl(false, true); -} - -function testExperimentalPolicy() { - testImpl(true, false); -} - -function test() { - testImpl(false, false); -} - -function testImpl(experimental, preescapedPolicy) { - if (tests.length === 0) - return finishTesting(); - - var baseURL = "/security/contentSecurityPolicy/"; - var current = tests.shift(); - var iframe = document.createElement("iframe"); - - var policy = current[1]; - if (!preescapedPolicy) - policy = encodeURIComponent(policy); - - var scriptToLoad = baseURL + encodeURIComponent(current[2]); - if (current[2].match(/^data:/) || current[2].match(/^https?:/)) - scriptToLoad = encodeURIComponent(current[2]); - - iframe.src = baseURL + "resources/echo-script-src.pl?" + - "experimental=" + (experimental ? "true" : "false") + - "&should_run=" + encodeURIComponent(current[0]) + - "&csp=" + policy + "&q=" + scriptToLoad; - if (current[3] !== undefined) - iframe.src += "&nonce=" + encodeURIComponent(current[3]); - - iframe.onload = function() { - testImpl(experimental, preescapedPolicy); - }; - document.body.appendChild(iframe); -} - -function finishTesting() { - if (window.testRunner) { - setTimeout("testRunner.notifyDone()", 0); - } - return true; -} diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/referrer-test.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/referrer-test.js deleted file mode 100644 index 7dafc9f9cf5..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/referrer-test.js +++ /dev/null @@ -1,62 +0,0 @@ -var ReferrerTest = { - NO_REFERRER: "no-referrer", - NO_REFERRER_WHEN_DOWNGRADE: "no-referrer-when-downgrade", - ORIGIN: "origin", - ORIGIN_WHEN_CROSS_ORIGIN: "origin-when-cross-origin", - UNSAFE_URL: "unsafe-url", - - INVALID: "invalid", - EMPTY: "", - - HTTP: "http", - HTTPS: "https", - - bindHandler: function(func) { - window.addEventListener("message", function(e) { - ReferrerTest.referrerResult = undefined; - func(e.data); - finishJSTest(); - }); - }, - - base: function(scheme) { - return scheme == "http" ? "http://127.0.0.1:8000/" : "https://127.0.0.1:8443/"; - }, - - generateFrameURL: function(policy, from, to) { - return ReferrerTest.base(from) + "security/contentSecurityPolicy/resources/referrer-test.php?policy=" + policy + "&to=" + to; - }, - - injectFrame: function(policy, from, to) { - var iframe = document.createElement("iframe"); - iframe.src = ReferrerTest.generateFrameURL(policy, from, to); - document.body.appendChild(iframe); - } -}; - -function expectFullReferrer(policy, from, to) { - ReferrerTest.bindHandler(function(referrer) { - ReferrerTest.referrerResult = referrer; - shouldBeEqualToString("ReferrerTest.referrerResult", ReferrerTest.generateFrameURL(policy, from, to)); - }); - ReferrerTest.injectFrame(policy, from, to); -} - -function expectNoReferrer(policy, from, to) { - ReferrerTest.bindHandler(function(referrer) { - ReferrerTest.referrerResult = referrer; - shouldBeEqualToString("ReferrerTest.referrerResult", ""); - }); - ReferrerTest.injectFrame(policy, from, to); -} - -function expectOriginReferrer(policy, from, to) { - ReferrerTest.bindHandler(function(referrer) { - ReferrerTest.referrerResult = referrer; - shouldBeEqualToString("ReferrerTest.referrerResult", ReferrerTest.base(from)); - }); - ReferrerTest.injectFrame(policy, from, to); -} - -window.wasPostTestScriptParsed = true; -window.jsTestIsAsync = true; diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/reflected-xss-and-xss-protection.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/reflected-xss-and-xss-protection.js deleted file mode 100644 index a7ba8ebbd0c..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/reflected-xss-and-xss-protection.js +++ /dev/null @@ -1,41 +0,0 @@ -if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.dumpChildFramesAsText(); - testRunner.setXSSAuditorEnabled(true); - testRunner.waitUntilDone(); -} - -function testMixedHeader(csp, xssProtection) { - var params = [ - 'q= - - - diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/securitypolicy-tests-base.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/securitypolicy-tests-base.js deleted file mode 100644 index f403e52e62a..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/securitypolicy-tests-base.js +++ /dev/null @@ -1,18 +0,0 @@ -if (window.testRunner) - testRunner.dumpAsText(); - -function log(msg) { - var txt = document.createTextNode(msg); - document.querySelector('body').appendChild(txt); - document.querySelector('body').appendChild(document.createElement('br')); -} - -function injectPolicy(policy) { - var meta = document.createElement('meta'); - meta.setAttribute('http-equiv', 'Content-Security-Policy'); - meta.setAttribute('content', policy); - document.head.appendChild(meta); -} - -if (!document.securityPolicy) - log('FAIL document.securityPolicy is not defined.') diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/securitypolicyviolation-test.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/securitypolicyviolation-test.js deleted file mode 100644 index cd16d94b3e0..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/securitypolicyviolation-test.js +++ /dev/null @@ -1,13 +0,0 @@ -window.jsTestIsAsync = true; - -document.addEventListener('securitypolicyviolation', function handleEvent(e) { - window.e = e; - for (key in expectations) - shouldBe('window.e.' + key, JSON.stringify(expectations[key])); - finishJSTest(); -}); - -window.addEventListener('load', function() { - debug('Kicking off the tests:'); - run(); -}); diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/shared-worker-make-xhr.js b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/shared-worker-make-xhr.js deleted file mode 100644 index 04e68d61b4f..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/shared-worker-make-xhr.js +++ /dev/null @@ -1,10 +0,0 @@ -onconnect = function(event) { - var port = event.ports[0]; - try { - var xhr = new XMLHttpRequest; - xhr.open("GET", "http://www1.{{host}}:{{ports[http][0]}}/content-security-policy/blink-contrib/resources/blue.css", true); - port.postMessage("xhr allowed"); - } catch (e) { - port.postMessage("xhr blocked"); - } -}; diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/style.xsl b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/style.xsl deleted file mode 100644 index 6d83dfc059b..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/style.xsl +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - Style sheet applied. - - - - diff --git a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/transform-to-img.xsl b/testing/web-platform/tests/content-security-policy/blink-contrib/resources/transform-to-img.xsl deleted file mode 100644 index 8d4ccf33487..00000000000 --- a/testing/web-platform/tests/content-security-policy/blink-contrib/resources/transform-to-img.xsl +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - Here is an image: - - - - - diff --git a/testing/web-platform/tests/dom/nodes/Element-matches.html b/testing/web-platform/tests/dom/nodes/Element-matches.html index 44e5112ee35..e04c0f9d19a 100644 --- a/testing/web-platform/tests/dom/nodes/Element-matches.html +++ b/testing/web-platform/tests/dom/nodes/Element-matches.html @@ -12,16 +12,14 @@
This test requires JavaScript.
+ + + +

LookupNamespaceURI and IsDefaultNamespace

+
+ + + diff --git a/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.html b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.html index 1899882ed6a..159b0b967a8 100644 --- a/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.html +++ b/testing/web-platform/tests/dom/nodes/ParentNode-querySelector-All.html @@ -10,17 +10,14 @@
This test requires JavaScript.
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html index 0f7b9cdf8f7..5e6b8cbe168 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html index aacf82bea18..0adc65f828b 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/fetch-request/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/fetch-request/top-level/keep-scheme-redirect/allowed.https.html index 93a02452cee..260fb14b042 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/fetch-request/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/fetch-request/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html index b21770be3b3..9b18ebb78b2 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: fetch-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/form-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/form-tag/top-level/keep-scheme-redirect/allowed.https.html index 6f551bef74a..742363922fb 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/form-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/form-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/form-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/form-tag/top-level/no-redirect/allowed.https.html index 6f00a97c23c..3f781b8201a 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/form-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/form-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: form-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/iframe-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/iframe-tag/top-level/keep-scheme-redirect/allowed.https.html index dd96415dce3..f584e0be95a 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/iframe-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/iframe-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html index 0b627378b1a..eb24a71a796 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: iframe-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html index c1f35d39a74..77adba6442a 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html index 46251b244b8..b08d413e8eb 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-css-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-css-tag/top-level/keep-scheme-redirect/allowed.https.html index 4a502ef111d..606887e3dd5 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-css-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-css-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html index d9761930854..2f4f750de9f 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-css-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-prefetch-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-prefetch-tag/top-level/keep-scheme-redirect/allowed.https.html index 69d69d3a73c..a047941dcd4 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-prefetch-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-prefetch-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html index e482ae3500e..bd24109afe2 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/object-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/object-tag/top-level/keep-scheme-redirect/allowed.https.html index 0bc7b32d141..d1be723f15d 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/object-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/object-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/object-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/object-tag/top-level/no-redirect/allowed.https.html index 412894cc620..3f8ec136a1c 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/object-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/object-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: object-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html index 8c1400c0979..3ae09e2e3f3 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html index bb40013c9c8..883c0bbdf78 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: picture-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/script-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/script-tag/top-level/keep-scheme-redirect/allowed.https.html index e7a11db559f..cb3528e03c9 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/script-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/script-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/script-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/script-tag/top-level/no-redirect/allowed.https.html index b94f116e47f..7bffa299c5d 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/script-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/script-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: script-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https.html index 48d4a288667..ce72664408e 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https.html index bd00bd6324e..b9ddc78ff18 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/worker-request/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/worker-request/top-level/keep-scheme-redirect/allowed.https.html index 7f772955e24..1a9053e4c3e 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/worker-request/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/worker-request/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html index 620ec69295e..0488b133755 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: worker-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html index 7994c9c9a4f..23f0a1fc89d 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html index 968a1961dff..7baa3e54a98 100644 --- a/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: http-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: xhr-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html index 420d1505a8c..721e31d399a 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html index 51fb3a591e6..e78f5493f91 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: fetch-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/form-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/form-tag/top-level/no-redirect/allowed.https.html index fc4c0869503..7b8652238ff 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/form-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/form-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: form-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html index 6a5650251a4..a3430f19368 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: iframe-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html index 7cedf27a751..46ece8f0caa 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/img-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html index 7b61d3cdd26..51d06274602 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-css-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html index 8ff7c5427d0..3763052b387 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/object-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/object-tag/top-level/no-redirect/allowed.https.html index 727c13ac86b..7a5e5dfa350 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/object-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/object-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: object-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html index fd0f5781633..c9885eb8577 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: picture-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/script-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/script-tag/top-level/no-redirect/allowed.https.html index 97fd7c54678..c0e7eb86796 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/script-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/script-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: script-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https.html index 47ce1138658..2799f5af02f 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/video-tag/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html index dfe4c0d2b96..091bc03c161 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: worker-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html index 890c5a068e0..4044ccec1fc 100644 --- a/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Allowed content + + + expectation: allowed"> - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: meta-csp
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: xhr-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html index ef20ab3dd20..b30f28b2aab 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html index 7947998f3b1..c13fd88e47e 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/fetch-request/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/fetch-request/top-level/keep-scheme-redirect/allowed.https.html index 259edb91093..9045019de11 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/fetch-request/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/fetch-request/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html index e2ad2c00a11..d4b8292af32 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: fetch-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/form-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/form-tag/top-level/keep-scheme-redirect/allowed.https.html index c1fbed161ac..a640ddee7d9 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/form-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/form-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/form-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/form-tag/top-level/no-redirect/allowed.https.html index ea646752bc6..48f005a386e 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/form-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/form-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: form-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/iframe-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/iframe-tag/top-level/keep-scheme-redirect/allowed.https.html index fb7626fcfb8..f44a0b54d66 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/iframe-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/iframe-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html index e0e31ce25e1..9cd4f1ba421 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/iframe-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: iframe-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html index 3732ca0c34b..54bb60accf1 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/no-redirect/allowed.https.html index cd098fcc6bc..26d7d2390ae 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/img-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-css-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-css-tag/top-level/keep-scheme-redirect/allowed.https.html index 98dc8f5b8b0..7d620f8da93 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-css-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-css-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html index 2cf47e953ac..f6d23405dd5 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-css-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-css-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-prefetch-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-prefetch-tag/top-level/keep-scheme-redirect/allowed.https.html index ff96861c443..c3ea33fdb70 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-prefetch-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-prefetch-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html index a590f6a0013..4c591115391 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/link-prefetch-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/object-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/object-tag/top-level/keep-scheme-redirect/allowed.https.html index 90eeccc4346..ebfb5195eb1 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/object-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/object-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/object-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/object-tag/top-level/no-redirect/allowed.https.html index 59c4b5b27e2..f5ffcf3a8b2 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/object-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/object-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: object-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html index fa4e129441e..57efd6f5ec4 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html index cb0c1c27c1c..e3113a84c9f 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/picture-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: picture-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/script-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/script-tag/top-level/keep-scheme-redirect/allowed.https.html index 964ef1f74c4..9dc0bb122c4 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/script-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/script-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/script-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/script-tag/top-level/no-redirect/allowed.https.html index 1f63f808b60..bad7e7f2104 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/script-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/script-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: script-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https.html index a27066a3de4..f044783e62b 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/no-redirect/allowed.https.html index 19a05ae3f2b..fd0a1f923a7 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/video-tag/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/worker-request/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/worker-request/top-level/keep-scheme-redirect/allowed.https.html index 7e0fb6d0420..d720fc4fa99 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/worker-request/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/worker-request/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/worker-request/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/worker-request/top-level/no-redirect/allowed.https.html index 7176f33e09a..bd69a14a9de 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/worker-request/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/worker-request/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: worker-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html index 109dd139400..9da0d9f98ec 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html index d7725fd0f27..b0fff36eb94 100644 --- a/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html +++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Allowed content + + - - - - - - -

Allowed content

-

Test behavior of allowed content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-https
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: xhr-request
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 539754e8d07..012bd3540a1 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html index 3b2e413efec..54fbe3a8477 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html index d135154c8f7..f9555455807 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index d239302da25..277d4789180 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html index b4742c92b8b..582ed6012b1 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index be3c57b5905..37d4db54b49 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 7d8b398b0a6..b4957a41eb1 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html index c89b2df2bba..e910a0ab7be 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 919be4b5bd8..1f8763010f0 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index cf64424bece..7376626e2e1 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html index d5bcff9defa..fc123d9638d 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 29b7c7d6150..f7fd32cbf9b 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 2563337805f..8ebd99b0118 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html index a3fb49fdc6f..b7743daa64c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index fa599d1c9e8..3fe162a2f7c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/object-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 00d7cd5127a..6f71158c216 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html index 6712dfda071..48012dfe550 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index d2c14742359..b76c48a658a 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/picture-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index bf7ef43097c..61f10dfbff3 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html index b3d6c9eef0b..69210c6061d 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 643daa0c202..a2201a2132a 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/script-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 77d1f3e6ff3..8fc3283a0ac 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html index 1f2cf69ab3e..21f63bd7307 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html index bf8eaef23d9..d4c437147aa 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 76d3dddf51e..314f0978905 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html index 6c227ca5f8c..d44e65bcd19 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 18e2fbfc73f..973db8006fc 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html index bf6576a67f6..c03b96f01fa 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html index 91d1a3f1265..a7ce2a53055 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 3cacff2de7d..1eec54d3b2c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index eb2b540f545..6d67e4d0e40 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html index c94668ad726..0d8b5ebdbd1 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 3f74ebf7bc5..326ca747cb4 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/form-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index a3d5fddcb1c..35e3102a5dd 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html index e8c3c209671..eaa1cc5d729 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 8a1708b4e0a..ff99ecf9bbd 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/iframe-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index c5dde9eaa3f..b93d1778422 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html index da5b01e6b1f..b23f9f0eb68 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index b852778af0c..122ee404dc7 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/link-css-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 3045cec23d2..4c43f3aea64 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html index e13d6d25b37..27da8b421be 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 974e6b771da..01df78229ff 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/object-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index e45e810791e..27e971ac49c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html index 32d1c139e43..0fe505a4b05 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 6dbd29b3e05..d066d7f4af1 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/picture-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index ef2583c98f5..011e515da17 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html index 7e9799a483e..5c8d860a695 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index e2341178abf..123e53d2027 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/script-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 741ac1d2337..735c267a88a 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html index f17779c3a86..d70b8576897 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html index f05454aaa7f..bf77ac6d77e 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/worker-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html index bbeb517dd65..f8509416232 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html index 272556d9822..0dd9e88e885 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 11edffe12af..eb7f7ea2c73 100644 --- a/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html index a320a2ad190..ccc8e9b0b86 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html index c02e468a94e..147bd58578d 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html index 0f4c63bfe92..84af99aca91 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html index 98dd2c36fe2..bf9b606aed9 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html index 956d09f91b0..128c08dcd6e 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html index 6f2a7c1b14e..debd088dbb9 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html index 3a8e8aefc5c..4872269168d 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html index 52f49cc0950..b4bfdb8781c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html index 68a41936b77..39a44b4524f 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html index 065f3322f7f..85be9eb2b7d 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html index 21195e63b87..f5a0bf5dc92 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html index 9d9ae1a5b11..6a70032ecdf 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/iframe-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html index c692dddfda4..68b5ac7066c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/link-css-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html index 0b74f62647f..a71d608c404 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/object-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html index 3a086d69def..b1cf804b339 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/picture-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html index 45028df06e5..05201512b34 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/script-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html index 48d69822c97..599a5280f19 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html index 08215b4aecc..fd22ba37e55 100644 --- a/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Blockable content + + + expectation: blocked"> - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 7719e757c7d..f35fd03dae8 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html index 0c9cc94d746..3b2d158d631 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 5bef9697f3c..24a1e8671d8 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index fa08dd71aff..aaeaf76737f 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 073e4c1b261..a649f4de484 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 971bbfccd73..fa1d0fe9094 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 1f01aade06f..0dad760aad3 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 8eca3a1b2eb..ed11ad73e8d 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index fd5a0e86605..de84e1278b6 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index cc5e4864e4b..13c536f3eb5 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 7091e351662..e941030043e 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 98d50834796..c9efe54e44a 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 0335c8ecc47..23e6badf7ea 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/no-redirect/no-opt-in-blocks.https.html index f50f0aa5db2..482024535f9 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index d61c4c8ad65..f91df5037e7 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/object-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 15dba41092a..09fadc8d3fb 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 0846e19e785..63505012881 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 8d3684a05c5..c3bedd387d7 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/picture-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 8327609cb0b..4c375acd157 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 0d043a69002..21d15255719 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 9d56544f27d..cd56451c5e4 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/script-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index b536c01465e..4feea4b7dc0 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html index da677d1a301..2d4f15b13e2 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index da62f80f75c..a6782c7e5b8 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 64b05b0fcee..b2ee591a74a 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html index fe1c2531791..e49db79f3d3 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index d719df447bd..ffd8aeb9c0b 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index f09de3a87c2..d7aa3899bfa 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html index c97f703f5c4..55c768525d1 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index a83aa353695..13de80df73c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: fetch-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 6c5e403c488..45a2764ade6 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 20651d5552f..09e948a84b5 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 4a7fc77ae4c..f72d269d11e 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/form-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: form-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 352f5af16ce..a69f2bb412e 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 37c55c40dfc..f98fe6c4cdf 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 75f0e6f543d..b891c73e817 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/iframe-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: iframe-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index a9b3c3001bc..11d8f4877a7 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 094ea4f0dd4..ce383d9aacb 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index efad36e8b4c..67b58e0096c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/link-css-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: link-css-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 0670e6ac299..190b66b0d62 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 09fc02e5234..c03d5036a38 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 6ff553e4f3f..d9a16660981 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/object-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: object-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index bbf3a5d6c24..0b2a8c8ff5a 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 51d6568f63f..532c97bf066 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 86771b07327..662fc90485a 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/picture-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: picture-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index 465f68eb4c8..cc1c051a364 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/no-redirect/no-opt-in-blocks.https.html index 546e32f28ee..23efca0a54c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 40ab7e08358..69e151519bb 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/script-tag/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: script-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index f21e6a1f205..065ff5ba526 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html index 3cee8fc6a31..3cd8a67482c 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index 34ce2e6b7c0..3b3e17c2777 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/worker-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: worker-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html index de05e8f9e74..897354a798a 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html index be1c31bebdf..ee787d05aa3 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html index ed2d3e2834d..9a9085b86eb 100644 --- a/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Blockable content + + - - - - - - -

Blockable content

-

Test behavior of blockable content.

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: xhr-request
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/generic/common.js b/testing/web-platform/tests/mixed-content/generic/common.js index d500f7ef52a..54fd50f7531 100644 --- a/testing/web-platform/tests/mixed-content/generic/common.js +++ b/testing/web-platform/tests/mixed-content/generic/common.js @@ -358,3 +358,4 @@ function requestViaObject(url) { // mode. function SanityChecker() {} SanityChecker.prototype.checkScenario = function() {}; +SanityChecker.prototype.setFailTimeout = function(test, timeout) {}; diff --git a/testing/web-platform/tests/mixed-content/generic/mixed-content-test-case.js b/testing/web-platform/tests/mixed-content/generic/mixed-content-test-case.js index df140c9c47b..4200b6d704c 100644 --- a/testing/web-platform/tests/mixed-content/generic/mixed-content-test-case.js +++ b/testing/web-platform/tests/mixed-content/generic/mixed-content-test-case.js @@ -85,18 +85,7 @@ function MixedContentTestCase(scenario, description, sanityChecker) { var mixed_content_test = async_test(description); function runTest() { - var testCompleted = false; - - // Due to missing implementations, tests time out, so we fail them early. - // TODO(kristijanburnik): Once WPT rolled in: - // https://github.com/w3c/testharness.js/pull/127 - // Refactor to make use of step_timeout. - setTimeout(function() { - mixed_content_test.step(function() { - assert_true(testCompleted, "Expected test to complete."); - mixed_content_test.done(); - }) - }, 1000); + sanityChecker.setFailTimeout(mixed_content_test); var key = guid(); var value = guid(); @@ -147,7 +136,6 @@ function MixedContentTestCase(scenario, description, sanityChecker) { "'."); }, "Check if request was sent."); mixed_content_test.done(); - testCompleted = true; }); } // runTest diff --git a/testing/web-platform/tests/mixed-content/generic/sanity-checker.js b/testing/web-platform/tests/mixed-content/generic/sanity-checker.js index c711e0ee236..55a103adf0f 100644 --- a/testing/web-platform/tests/mixed-content/generic/sanity-checker.js +++ b/testing/web-platform/tests/mixed-content/generic/sanity-checker.js @@ -1,6 +1,6 @@ // The SanityChecker is used in debug mode to identify problems with the -// structure of the testsuite. In release mode it is mocked out to do nothing. - +// structure of the testsuite and to force early test failures. +// In release mode it is mocked out to do nothing. function SanityChecker() {} SanityChecker.prototype.checkScenario = function(scenario, resourceInvoker) { @@ -36,3 +36,18 @@ SanityChecker.prototype.checkScenario = function(scenario, resourceInvoker) { }, "[MixedContentTestCase] The test scenario should be valid."); } + +// For easier debugging runs, we can fail a test earlier. +SanityChecker.prototype.setFailTimeout = function(test, timeout) { + // Due to missing implementations, tests time out, so we fail them early. + // TODO(kristijanburnik): Once WPT rolled in: + // https://github.com/w3c/testharness.js/pull/127 + // Refactor to make use of step_timeout. + setTimeout(function() { + test.step(function() { + assert_equals(test.phase, test.phases.COMPLETE, + "Expected test to complete."); + test.done(); + }) + }, timeout || 1000); +} diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 3cae7b1b2f2..ac620c1075b 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html index a6597f1f437..abc81b30191 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: audio-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 3b0dd9786c9..27c67b081dd 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 9a63f99ae00..1816b4231bd 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html index e0d760323b7..509fc34750f 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: img-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index aa689fad1a4..61baeee7944 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index a95ea4adfd2..743515ed351 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html index 87338d7de57..88a54250a12 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index f319137a7ca..2098a60b628 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/link-prefetch-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 767bbaa01e5..029d34c4f41 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html index 892c5f10d1f..c72ca267fcb 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: video-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 10513766f2e..b50a7b70a01 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/cross-origin-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 0562b6ed924..5fd63aa6d0b 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html index 0246af6a961..e6f742213cc 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: audio-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 57989fdbccc..522e9442072 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/audio-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index d496ea5435f..ad615e9b23f 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html index 450b5556579..b6f92431a3a 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: img-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 200d50cbec4..580f4b5492f 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/img-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index fde66246b8e..fa8bd8a1f49 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html index 21f01e59b78..685f34582a0 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index 4e042058e5e..ab0378461d1 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/link-prefetch-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html index 532b9631902..8b64104bd2f 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html index e605a73136b..abe3385b06a 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: video-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html index e71c10ae4c3..78d9f8d5d4e 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/http-csp/same-host-http/video-tag/top-level/swap-scheme-redirect/opt-in-blocks.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: http-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html index 40b5cddbdde..ddc860ba2fc 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Optionally-blockable content + + + expectation: blocked"> - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: audio-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html index 7febc67f326..44fdb8b7aa1 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Optionally-blockable content + + + expectation: blocked"> - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: img-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html index 293be460d2f..b5de46754dd 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Optionally-blockable content + + + expectation: blocked"> - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html index a4376a209f2..2aebedc7857 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/cross-origin-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Optionally-blockable content + + + expectation: blocked"> - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: meta-csp
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: video-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html index ade9c060d40..e066dd1e3e7 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Optionally-blockable content + + + expectation: blocked"> - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: audio-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html index f4bc1bc74b6..0572c8079bc 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/img-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Optionally-blockable content + + + expectation: blocked"> - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: img-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html index 29a5afc0c99..3b1d36af291 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/link-prefetch-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Optionally-blockable content + + + expectation: blocked"> - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html index 4a098da56b4..c78aa6b9942 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/meta-csp/same-host-http/video-tag/top-level/no-redirect/opt-in-blocks.https.html @@ -1,43 +1,25 @@ - + Mixed-Content: Optionally-blockable content + + + expectation: blocked"> - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: meta-csp
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: video-tag
-                                 expectation: blocked
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html index 235dcab68a6..15fe5d2afc1 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html index f0f024cf794..2da4a2b9361 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html index 76724ecbf69..8b610ada7db 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html index dccc6c8fad1..5a7bdc3b538 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html index 4c4933e919b..6c0a9f5e686 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html index f779562be89..c9ffbfd0c70 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html index 67f09927adb..76629861437 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/no-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/no-redirect/no-opt-in-allows.https.html index 935d48e8a36..5bcce0017db 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/no-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/no-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html index 84c2eb421d7..31230323496 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/link-prefetch-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html index 7178e0fcf9d..561a2f7c1b5 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/no-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/no-redirect/no-opt-in-allows.https.html index 6cc20ef2fdc..e02134b4acf 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/no-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/no-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html index 2e8225bc21e..f90575c137a 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/cross-origin-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: cross-origin-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html index 203f93f430c..cd4d8a52e76 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html index 7d096f0be49..20d31cf690e 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/no-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html index 8af53520894..2ed233dc885 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/audio-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: audio-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html index 355dc84511b..aab662fc3ab 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html index 90e3843733f..6f0a8fdedef 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/no-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html index d8d2853b058..f55cce43713 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/img-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: img-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html index 30969a0623e..26c76572040 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/no-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/no-redirect/no-opt-in-allows.https.html index 6cf5133166c..582f6c63a5d 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/no-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/no-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html index 8faeaa0e512..a7feabccba1 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/link-prefetch-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: link-prefetch-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html index 139a87d3013..68bfc2b84a8 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/keep-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: keep-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/no-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/no-redirect/no-opt-in-allows.https.html index 847d2a7000b..2e5eff5a74e 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/no-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/no-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: no-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html index 3deb905f760..8c5bd7b0806 100644 --- a/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html +++ b/testing/web-platform/tests/mixed-content/optionally-blockable/no-opt-in/same-host-http/video-tag/top-level/swap-scheme-redirect/no-opt-in-allows.https.html @@ -1,10 +1,12 @@ - + Mixed-Content: Optionally-blockable content + + - - - - - - -

Optionally-blockable content

-

Test behavior of optionally-blockable content

-
opt_in_method: no-opt-in
-                                 origin: same-host-http
-                                 source_scheme: https
-                                 context_nesting: top-level
-                                 redirection: swap-scheme-redirect
-                                 subresource: video-tag
-                                 expectation: allowed
- -

See specification - details for this test.

- -
+
diff --git a/testing/web-platform/tests/notifications/Notification-permission.html b/testing/web-platform/tests/notifications/Notification-permission.html deleted file mode 100644 index d6501b5b5c3..00000000000 --- a/testing/web-platform/tests/notifications/Notification-permission.html +++ /dev/null @@ -1,17 +0,0 @@ - - -Web Notifications Test: Notification - permission (basic) - - - - - - -
- - - diff --git a/testing/web-platform/tests/notifications/Notification-requestPermission-denied-manual.html b/testing/web-platform/tests/notifications/Notification-requestPermission-denied-manual.html deleted file mode 100644 index 583e80e6920..00000000000 --- a/testing/web-platform/tests/notifications/Notification-requestPermission-denied-manual.html +++ /dev/null @@ -1,22 +0,0 @@ - - -Web Notifications Test: Notification - requestPermission (deny) - - - - - - - -

Test Step:

-

1. When ask the user whether showing notifications, make sure choose deny.

-
- - - diff --git a/testing/web-platform/tests/notifications/Notification-requestPermission-granted-manual.html b/testing/web-platform/tests/notifications/Notification-requestPermission-granted-manual.html deleted file mode 100644 index 4cf29d2731f..00000000000 --- a/testing/web-platform/tests/notifications/Notification-requestPermission-granted-manual.html +++ /dev/null @@ -1,22 +0,0 @@ - - -Web Notifications Test: Notification - requestPermission (allow) - - - - - - - -

Test Step:

-

1. When ask the user whether showing notifications, make sure choose allow.

-
- - - diff --git a/testing/web-platform/tests/notifications/README.md b/testing/web-platform/tests/notifications/README.md deleted file mode 100644 index 821255358f1..00000000000 --- a/testing/web-platform/tests/notifications/README.md +++ /dev/null @@ -1,5 +0,0 @@ -Web Notifications test suite. - -Latest Editor's Draft: http://dvcs.w3.org/hg/notifications/raw-file/tip/Overview.html - -Latest Technical Report: http://www.w3.org/TR/notifications/ diff --git a/testing/web-platform/tests/notifications/body-basic-manual.html b/testing/web-platform/tests/notifications/body-basic-manual.html new file mode 100644 index 00000000000..a479917aeef --- /dev/null +++ b/testing/web-platform/tests/notifications/body-basic-manual.html @@ -0,0 +1,28 @@ + + +Notification.body (basic) + + + + + +
+ diff --git a/testing/web-platform/tests/notifications/body-empty-manual.html b/testing/web-platform/tests/notifications/body-empty-manual.html new file mode 100644 index 00000000000..a94f08e1c5d --- /dev/null +++ b/testing/web-platform/tests/notifications/body-empty-manual.html @@ -0,0 +1,31 @@ + + +Notification.body (empty string) + + + + + +
+ diff --git a/testing/web-platform/tests/notifications/common.js b/testing/web-platform/tests/notifications/common.js new file mode 100644 index 00000000000..ecfa0e3c2d9 --- /dev/null +++ b/testing/web-platform/tests/notifications/common.js @@ -0,0 +1,48 @@ +function createPassFail(condition, test, cleanup, cleanupParam) { + var div = document.querySelector("#passfail") + var para = document.createElement("p") + var pass = document.createElement("button") + var fail = document.createElement("button") + var style = "font-family: monospace" + para.innerHTML = condition + + ', press the PASS button;' + + ' otherwise press the FAIL button.', + pass.innerHTML = "PASS" + fail.innerHTML = "FAIL" + pass.setAttribute("style", style) + fail.setAttribute("style", style) + pass.addEventListener("click", function () { + clearPassFail() + cleanup(cleanupParam) + test.done() + }, false) + fail.addEventListener("click", function () { + clearPassFail() + cleanup(cleanupParam) + test.force_timeout() + test.set_status(test.FAIL) + test.done() + }, false) + document.body.appendChild(div) + div.appendChild(para) + div.appendChild(pass) + div.appendChild(fail) +} +function clearPassFail() { + document.querySelector("#passfail").innerHTML = "" +} +function closeNotifications(notifications) { + for (var i=0; i < notifications.length; i++) { + notifications[i].close() + } +} +function hasNotificationPermission() { + Notification.requestPermission() + if (Notification.permission != "granted") { + alert("TEST NOT RUN. Change your browser settings so that" + + " notifications for this origin are allowed, and then re-run" + + " this test.") + return false + } + return true +} diff --git a/testing/web-platform/tests/notifications/constructor-basic.html b/testing/web-platform/tests/notifications/constructor-basic.html new file mode 100644 index 00000000000..a36a8ce3047 --- /dev/null +++ b/testing/web-platform/tests/notifications/constructor-basic.html @@ -0,0 +1,21 @@ + + +Notification constructor (basic) + + + + + diff --git a/testing/web-platform/tests/notifications/constructor-invalid.html b/testing/web-platform/tests/notifications/constructor-invalid.html new file mode 100644 index 00000000000..88df165e169 --- /dev/null +++ b/testing/web-platform/tests/notifications/constructor-invalid.html @@ -0,0 +1,19 @@ + + +Notification constructor (invalid) + + + + + diff --git a/testing/web-platform/tests/notifications/event-onclick-manual.html b/testing/web-platform/tests/notifications/event-onclick-manual.html index 5d06caea5f2..0d48d06ae8d 100644 --- a/testing/web-platform/tests/notifications/event-onclick-manual.html +++ b/testing/web-platform/tests/notifications/event-onclick-manual.html @@ -1,28 +1,25 @@ -Web Notifications Test: notification - onclick (basic) +Notification.onclick (basic) - - - -
- - - + + diff --git a/testing/web-platform/tests/notifications/event-onclose.html b/testing/web-platform/tests/notifications/event-onclose.html index 27414dc4fe8..aee3213698e 100644 --- a/testing/web-platform/tests/notifications/event-onclose.html +++ b/testing/web-platform/tests/notifications/event-onclose.html @@ -1,31 +1,26 @@ -Web Notifications Test: notification - onclose (basic) +Notification.onclose (basic) - - - -
- - - + diff --git a/testing/web-platform/tests/notifications/event-onerror-default-manual.html b/testing/web-platform/tests/notifications/event-onerror-default-manual.html index 3e521801d4b..4a50de73662 100644 --- a/testing/web-platform/tests/notifications/event-onerror-default-manual.html +++ b/testing/web-platform/tests/notifications/event-onerror-default-manual.html @@ -1,27 +1,27 @@ -Web Notifications Test: notification - onerror (basic) +Notification.onerror (permission=default) - - - -
- - - + diff --git a/testing/web-platform/tests/notifications/event-onerror-denied-manual.html b/testing/web-platform/tests/notifications/event-onerror-denied-manual.html index 049bd3fe779..b90fb38cc10 100644 --- a/testing/web-platform/tests/notifications/event-onerror-denied-manual.html +++ b/testing/web-platform/tests/notifications/event-onerror-denied-manual.html @@ -1,37 +1,26 @@ -Web Notifications Test: notification - onerror (basic) +Notification.onerror (permission=denied) - - - -
-
- - - + diff --git a/testing/web-platform/tests/notifications/event-onshow.html b/testing/web-platform/tests/notifications/event-onshow.html index 8e3c7637ee1..7cc2be9de5b 100644 --- a/testing/web-platform/tests/notifications/event-onshow.html +++ b/testing/web-platform/tests/notifications/event-onshow.html @@ -1,29 +1,25 @@ -Web Notifications Test: notification - onshow (basic) +Notification.onshow (basic) - - - -
- - - + diff --git a/testing/web-platform/tests/notifications/icon-basic-manual.html b/testing/web-platform/tests/notifications/icon-basic-manual.html new file mode 100644 index 00000000000..32e8e0bbbd8 --- /dev/null +++ b/testing/web-platform/tests/notifications/icon-basic-manual.html @@ -0,0 +1,28 @@ + + +Notification.icon (basic) + + + + + +
+ diff --git a/testing/web-platform/tests/notifications/icon-empty-manual.html b/testing/web-platform/tests/notifications/icon-empty-manual.html new file mode 100644 index 00000000000..a4b288fa597 --- /dev/null +++ b/testing/web-platform/tests/notifications/icon-empty-manual.html @@ -0,0 +1,27 @@ + + +Notification.icon (empty string) + + + + + +
+ diff --git a/testing/web-platform/tests/notifications/instance.html b/testing/web-platform/tests/notifications/instance.html index 2451b10c6a1..c0ebe7e6998 100644 --- a/testing/web-platform/tests/notifications/instance.html +++ b/testing/web-platform/tests/notifications/instance.html @@ -1,52 +1,63 @@ -Basic Notification instance tests +Notification instance basic tests diff --git a/testing/web-platform/tests/notifications/interfaces.html b/testing/web-platform/tests/notifications/interfaces.html index 71232e71249..5930086f598 100644 --- a/testing/web-platform/tests/notifications/interfaces.html +++ b/testing/web-platform/tests/notifications/interfaces.html @@ -1,6 +1,6 @@ -Web Notifications IDL tests +Notification interface IDL tests
@@ -74,7 +74,7 @@ var idlArray = new IdlArray(); } }); idlArray.add_objects({ - Notification: ['new Notification("foo")'], + Notification: ['new Notification("Running idlharness.")'], }); idlArray.test(); diff --git a/testing/web-platform/tests/notifications/notification-lang.html b/testing/web-platform/tests/notifications/lang.html similarity index 69% rename from testing/web-platform/tests/notifications/notification-lang.html rename to testing/web-platform/tests/notifications/lang.html index d36fc14e387..be1795c8c9e 100644 --- a/testing/web-platform/tests/notifications/notification-lang.html +++ b/testing/web-platform/tests/notifications/lang.html @@ -1,15 +1,10 @@ -Web Notifications Test: notification.lang +Notification.lang - - - -
- - +for (var i=0; i diff --git a/testing/web-platform/tests/notifications/notification-body-basic-manual.html b/testing/web-platform/tests/notifications/notification-body-basic-manual.html deleted file mode 100644 index 378ad4e3f1f..00000000000 --- a/testing/web-platform/tests/notifications/notification-body-basic-manual.html +++ /dev/null @@ -1,17 +0,0 @@ - - -Web Notifications Test: notification - body (basic) - - - - - - -

Test passes if a notification popups and the notification's body content is "Room 101".

- - - diff --git a/testing/web-platform/tests/notifications/notification-body-empty-manual.html b/testing/web-platform/tests/notifications/notification-body-empty-manual.html deleted file mode 100644 index 76be5eba6c5..00000000000 --- a/testing/web-platform/tests/notifications/notification-body-empty-manual.html +++ /dev/null @@ -1,17 +0,0 @@ - - -Web Notifications Test: notification - body (empty string) - - - - - - -

Test passes if a notification popups and the notification have no body content.

- - - diff --git a/testing/web-platform/tests/notifications/notification-close-manual.html b/testing/web-platform/tests/notifications/notification-close-manual.html deleted file mode 100644 index 7b58e26090c..00000000000 --- a/testing/web-platform/tests/notifications/notification-close-manual.html +++ /dev/null @@ -1,21 +0,0 @@ - - -Web Notifications Test: notification - close (basic) - - - - - - -

Test passes if a notification popups and it disappears after a while(about 3 seconds).

- - - diff --git a/testing/web-platform/tests/notifications/notification-constructor-basic.html b/testing/web-platform/tests/notifications/notification-constructor-basic.html deleted file mode 100644 index 7ed12b31d05..00000000000 --- a/testing/web-platform/tests/notifications/notification-constructor-basic.html +++ /dev/null @@ -1,20 +0,0 @@ - - -Web Notifications Test: notification - constructor (basic) - - - - - - -
- - - diff --git a/testing/web-platform/tests/notifications/notification-constructor-invalid.html b/testing/web-platform/tests/notifications/notification-constructor-invalid.html deleted file mode 100644 index d065e975e34..00000000000 --- a/testing/web-platform/tests/notifications/notification-constructor-invalid.html +++ /dev/null @@ -1,19 +0,0 @@ - - -Web Notifications Test: notification - constructor (invalid) - - - - - - -
- - - diff --git a/testing/web-platform/tests/notifications/notification-dir-auto-manual.html b/testing/web-platform/tests/notifications/notification-dir-auto-manual.html deleted file mode 100644 index 358aa619e7a..00000000000 --- a/testing/web-platform/tests/notifications/notification-dir-auto-manual.html +++ /dev/null @@ -1,18 +0,0 @@ - - -Web Notifications Test: notification - dir (dir attribute set to "auto") - - - - - - -

Test passes if a notification popups and the notification's direction is the left edge.

- - - diff --git a/testing/web-platform/tests/notifications/notification-dir-ltr-manual.html b/testing/web-platform/tests/notifications/notification-dir-ltr-manual.html deleted file mode 100644 index d8b74511f20..00000000000 --- a/testing/web-platform/tests/notifications/notification-dir-ltr-manual.html +++ /dev/null @@ -1,18 +0,0 @@ - - -Web Notifications Test: notification - dir (dir attribute set to "ltr") - - - - - - -

Test passes if a notification popups and the notification's direction is the left edge.

- - - diff --git a/testing/web-platform/tests/notifications/notification-dir-rtl-manual.html b/testing/web-platform/tests/notifications/notification-dir-rtl-manual.html deleted file mode 100644 index 544773c9991..00000000000 --- a/testing/web-platform/tests/notifications/notification-dir-rtl-manual.html +++ /dev/null @@ -1,18 +0,0 @@ - - -Web Notifications Test: notification - dir (dir attribute set to "rtl") - - - - - - -

Test passes if a notification popups and the notification's direction is the right edge.

- - - diff --git a/testing/web-platform/tests/notifications/notification-icon-basic-manual.html b/testing/web-platform/tests/notifications/notification-icon-basic-manual.html deleted file mode 100644 index 1d3a95147b1..00000000000 --- a/testing/web-platform/tests/notifications/notification-icon-basic-manual.html +++ /dev/null @@ -1,19 +0,0 @@ - - -Web Notifications Test: notification - icon (basic) - - - - - - -

Make sure connect to network.

-

Test passes if a notificaiton popups with a cat pictrue.

- - - diff --git a/testing/web-platform/tests/notifications/notification-icon-empty-manual.html b/testing/web-platform/tests/notifications/notification-icon-empty-manual.html deleted file mode 100644 index b153ed7f35c..00000000000 --- a/testing/web-platform/tests/notifications/notification-icon-empty-manual.html +++ /dev/null @@ -1,18 +0,0 @@ - - -Web Notifications Test: notification - icon (invalid) - - - - - - -

Test passes if a notificaiton popups and notification's icon content show nothing.

- - - diff --git a/testing/web-platform/tests/notifications/notification-tag-different-manual.html b/testing/web-platform/tests/notifications/notification-tag-different-manual.html deleted file mode 100644 index ee94e8b3ede..00000000000 --- a/testing/web-platform/tests/notifications/notification-tag-different-manual.html +++ /dev/null @@ -1,23 +0,0 @@ - - -Web Notifications Test: notification - tag (with different tag) - - - - - - -

Test passes if two notifications popups and the notification's body are different.

- - - diff --git a/testing/web-platform/tests/notifications/notification-tag-same-manual.html b/testing/web-platform/tests/notifications/notification-tag-same-manual.html deleted file mode 100644 index 5099e68c2a0..00000000000 --- a/testing/web-platform/tests/notifications/notification-tag-same-manual.html +++ /dev/null @@ -1,23 +0,0 @@ - - -Web Notifications Test: notification - tag (with same tag) - - - - - - -

Test passes if only one notification popups and the notification's body is "Room 202".

- - - diff --git a/testing/web-platform/tests/notifications/permission.html b/testing/web-platform/tests/notifications/permission.html new file mode 100644 index 00000000000..d8b201e42ef --- /dev/null +++ b/testing/web-platform/tests/notifications/permission.html @@ -0,0 +1,14 @@ + + +Notification.permission (basic) + + + + + diff --git a/testing/web-platform/tests/notifications/requestPermission-denied-manual.html b/testing/web-platform/tests/notifications/requestPermission-denied-manual.html new file mode 100644 index 00000000000..a7ec052dba7 --- /dev/null +++ b/testing/web-platform/tests/notifications/requestPermission-denied-manual.html @@ -0,0 +1,22 @@ + + +Notification.requestPermission (permission=denied) + + + + + diff --git a/testing/web-platform/tests/notifications/requestPermission-granted-manual.html b/testing/web-platform/tests/notifications/requestPermission-granted-manual.html new file mode 100644 index 00000000000..970f4e3cbc8 --- /dev/null +++ b/testing/web-platform/tests/notifications/requestPermission-granted-manual.html @@ -0,0 +1,18 @@ + + +Notification.requestPermission (permission=granted) + + + + + + diff --git a/testing/web-platform/tests/notifications/tag-different-manual.html b/testing/web-platform/tests/notifications/tag-different-manual.html new file mode 100644 index 00000000000..e463e976701 --- /dev/null +++ b/testing/web-platform/tests/notifications/tag-different-manual.html @@ -0,0 +1,37 @@ + + +Notification.tag (two tags with different values) + + + + + +
+ diff --git a/testing/web-platform/tests/notifications/tag-same-manual.html b/testing/web-platform/tests/notifications/tag-same-manual.html new file mode 100644 index 00000000000..53ebfd35ce5 --- /dev/null +++ b/testing/web-platform/tests/notifications/tag-same-manual.html @@ -0,0 +1,37 @@ + + +Notification.tag (two tags with same value) + + + + + +
+ diff --git a/testing/web-platform/tests/referrer-policy/generic/common.js b/testing/web-platform/tests/referrer-policy/generic/common.js index f9c3ad9d19b..571aef1f79e 100644 --- a/testing/web-platform/tests/referrer-policy/generic/common.js +++ b/testing/web-platform/tests/referrer-policy/generic/common.js @@ -85,8 +85,6 @@ function wrapResult(url, server_data) { referrer: server_data.headers.referer, headers: server_data.headers } - - return result; } function queryIframe(url, callback) { diff --git a/testing/web-platform/tests/resources/docs/api.md b/testing/web-platform/tests/resources/docs/api.md index 6f25ad2a1fc..f3540c80e24 100644 Binary files a/testing/web-platform/tests/resources/docs/api.md and b/testing/web-platform/tests/resources/docs/api.md differ diff --git a/testing/web-platform/tests/resources/testharness.js b/testing/web-platform/tests/resources/testharness.js index 9ad4f9aa5c1..f4c66aae621 100644 --- a/testing/web-platform/tests/resources/testharness.js +++ b/testing/web-platform/tests/resources/testharness.js @@ -658,6 +658,14 @@ policies and contribution forms [3]. object.addEventListener(event, callback, false); } + function step_timeout(f, t) { + var outer_this = this; + var args = Array.prototype.slice.call(arguments, 2); + return setTimeout(function() { + f.apply(outer_this, args); + }, t * tests.timeout_multiplier); + } + expose(test, 'test'); expose(async_test, 'async_test'); expose(promise_test, 'promise_test'); @@ -666,6 +674,7 @@ policies and contribution forms [3]. expose(setup, 'setup'); expose(done, 'done'); expose(on_event, 'on_event'); + expose(step_timeout, 'step_timeout'); /* * Return a string truncated to the given length, with ... added at the end @@ -1422,6 +1431,14 @@ policies and contribution forms [3]. }); }; + Test.prototype.step_timeout = function(f, timeout) { + var test_this = this; + var args = Array.prototype.slice.call(arguments, 2); + return setTimeout(this.step_func(function() { + return f.apply(test_this, args); + }, timeout * tests.timeout_multiplier)); + } + Test.prototype.add_cleanup = function(callback) { this.cleanup_callbacks.push(callback); }; diff --git a/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html b/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html index f27e4e66f0c..95237a6fd97 100644 --- a/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html +++ b/testing/web-platform/tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html @@ -12,16 +12,14 @@
This test requires JavaScript.
- - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-003.html b/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-003.html deleted file mode 100644 index bd8ce05be77..00000000000 --- a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-003.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - -Shadow DOM Test: A_10_01_02_03 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html b/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html index 53f4a2ab328..bbc26bf733b 100644 --- a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html +++ b/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html @@ -37,7 +37,7 @@ test(unit(function (ctx) { range.setStart(span.firstChild, 0); range.setEnd(span.firstChild, 3); - var selection = window.getSelection(); + var selection = s.getSelection(); selection.removeAllRanges(); selection.addRange(range); diff --git a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005.html b/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005.html deleted file mode 100644 index 8ce777f5e33..00000000000 --- a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - -Shadow DOM Test: A_10_01_02_05 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html b/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html index 30b63067354..354c7a0e3c9 100644 --- a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html +++ b/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html @@ -24,7 +24,7 @@ policies and contribution forms [3]. diff --git a/testing/web-platform/tests/shadow-dom/html-elements-and-their-shadow-trees/test-004.html b/testing/web-platform/tests/shadow-dom/html-elements-and-their-shadow-trees/test-004.html index 579f9616a06..200ade6b1b8 100644 --- a/testing/web-platform/tests/shadow-dom/html-elements-and-their-shadow-trees/test-004.html +++ b/testing/web-platform/tests/shadow-dom/html-elements-and-their-shadow-trees/test-004.html @@ -43,33 +43,6 @@ test(unit(function (ctx) { assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered'); }), 'A_09_00_04_T01'); - - - -//test summary:first-of-type -test(unit(function (ctx) { - - var d = newRenderedHTMLDocument(ctx); - - // create element - var el = d.createElement('details'); - el.setAttribute('open', 'open'); - d.body.appendChild(el); - - el.innerHTML = '' + - '' + - 'This is a node that should be distributed' + - '' + - 'Unlucky content'; - - var s = el.createShadowRoot(); - s.innerHTML = ''; - - assert_true(d.querySelector('#shadow').offsetTop > 0, 'details should allow insertion point' + - 'with summary:first-of-type matching criteria'); - assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered'); - -}), 'A_09_00_04_T02'); diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/content-pseudo-element/test-001.html b/testing/web-platform/tests/shadow-dom/shadow-trees/content-pseudo-element/test-001.html index ffafc7795e5..dfb96741aa7 100644 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/content-pseudo-element/test-001.html +++ b/testing/web-platform/tests/shadow-dom/shadow-trees/content-pseudo-element/test-001.html @@ -36,7 +36,7 @@ A_04_04_01_T1.step(function () { //make shadow tree var ul = d.querySelector('ul.stories'); - var s = createSR(ul); + var s = ul.createShadowRoot(); var subdiv1 = d.createElement('div'); subdiv1.innerHTML = '
'; s.appendChild(subdiv1); diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/content-pseudo-element/test-002.html b/testing/web-platform/tests/shadow-dom/shadow-trees/content-pseudo-element/test-002.html index d583cfed4d6..e81d92bf4f6 100644 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/content-pseudo-element/test-002.html +++ b/testing/web-platform/tests/shadow-dom/shadow-trees/content-pseudo-element/test-002.html @@ -35,7 +35,7 @@ A_04_04_01_T2.step(function () { //make shadow tree var ul = d.querySelector('ul.stories'); - var s = createSR(ul); + var s = ul.createShadowRoot(); var subdiv1 = d.createElement('div'); subdiv1.innerHTML = '
'; s.appendChild(subdiv1); diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002-ref.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002-ref.html deleted file mode 100644 index 6cc4b52ec6a..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002-ref.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Shadow DOM - The older tree is inserted into shadow, and the original branch is inserted into content. - - - -
-

Younger tree's node

-

Older tree's node

-

Original tree's node

-
- - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002.html deleted file mode 100644 index 4d589b50550..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Shadow DOM Test - Tests shadow inserts older tree. - - - - - - - -
-

Original tree's node

-
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003-ref.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003-ref.html deleted file mode 100644 index 629821c2c75..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003-ref.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Shadow DOM - The shadow should insert original tree's node if no older shadow tree exists. - - - -
-

Younger tree's node

-

Older tree's node

-

Original tree's node

-
- - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003.html deleted file mode 100644 index b9f237275f9..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Shadow DOM Test - Tests shadow should insert original tree's node if no older shadow tree exists. - - - - - - - -
-

Original tree's node

-
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004-ref.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004-ref.html deleted file mode 100644 index 29d5eff0e21..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004-ref.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Shadow DOM - The only first shadow element is used. - - - -
-

1st shadow tree's node

-

2nd shadow tree's node

-
- - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004.html deleted file mode 100644 index 5dfffd13a9a..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Shadow DOM Test - The only first shadow element is used. - - - - - - - -
-

Original tree's node

-
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005-ref.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005-ref.html deleted file mode 100644 index 6d7b13af706..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005-ref.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Shadow DOM - Older shadow tree is not used - - - -
-

2nd shadow tree's node

-

Original tree's node

-
- - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005.html deleted file mode 100644 index 82d54d0cb87..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Shadow DOM Test - The older shadow tree is not used. - - - - - - - -
-

Original tree's node

-
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006-ref.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006-ref.html deleted file mode 100644 index ea90ce8ad35..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006-ref.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Shadow DOM - Content and shadow elements are both inserted - - - -
-

2nd shadow tree's node

-

Original tree's node

-

1st shadow tree's node

-
- - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006.html deleted file mode 100644 index a352be28790..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Shadow DOM Test - Content and shadow elements are both inserted. - - - - - - - -
-

Original tree's node

-
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-001.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-001.html deleted file mode 100644 index a62bcf32ed6..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-001.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - -Shadow DOM Test: A_04_05_01 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-002.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-002.html deleted file mode 100644 index a9e967878c2..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-002.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - -Shadow DOM Test: A_04_05_02 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-003.html b/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-003.html deleted file mode 100644 index 13dbe3f4e96..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-003.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - -Shadow DOM Test: A_04_05_03 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-006.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-006.html deleted file mode 100644 index b6731d5d867..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-006.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_01 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-007.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-007.html deleted file mode 100644 index f1cf07f1794..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-007.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_03 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-008.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-008.html deleted file mode 100644 index f90e04b3c40..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-008.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_04 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-009.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-009.html deleted file mode 100644 index 1dc5b81625d..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-009.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_05 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-010.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-010.html deleted file mode 100644 index 9ad8a6c0909..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-010.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_06 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-011.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-011.html deleted file mode 100644 index 4def9a0c648..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-011.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_07 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-012.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-012.html deleted file mode 100644 index a7dd85cd9df..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-012.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_08 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-013.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-013.html deleted file mode 100644 index 31e4f310a69..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-013.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_09 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-014.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-014.html deleted file mode 100644 index 3f0eaad05bc..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-014.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_10 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-015.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-015.html deleted file mode 100644 index a074086f88e..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-015.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_11 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-016.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-016.html deleted file mode 100644 index 919c3262624..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-016.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_12 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-017.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-017.html deleted file mode 100644 index 711c8c65add..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-017.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_13 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-018.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-018.html deleted file mode 100644 index 93f991fd45e..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-018.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_14 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-019.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-019.html deleted file mode 100644 index 8b7a07f5019..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-019.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_15 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-020.html b/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-020.html deleted file mode 100644 index 15ad4e620e3..00000000000 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-020.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - -Shadow DOM Test: A_04_03_06_16 - - - - - - - - - -
- - - diff --git a/testing/web-platform/tests/shadow-dom/shadow-trees/text-decoration-001.html b/testing/web-platform/tests/shadow-dom/shadow-trees/text-decoration-001.html index f22c3a3854e..47d5efda0e6 100644 --- a/testing/web-platform/tests/shadow-dom/shadow-trees/text-decoration-001.html +++ b/testing/web-platform/tests/shadow-dom/shadow-trees/text-decoration-001.html @@ -13,7 +13,7 @@ - - - - - -
- - - diff --git a/testing/web-platform/tests/subresource-integrity/alternate.css b/testing/web-platform/tests/subresource-integrity/alternate.css new file mode 100644 index 00000000000..0ea6d22ec77 --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/alternate.css @@ -0,0 +1 @@ +.testdiv{ background-color: red } diff --git a/testing/web-platform/tests/subresource-integrity/subresource-integrity.html b/testing/web-platform/tests/subresource-integrity/subresource-integrity.html index e1dab10814a..6bb6b4cf852 100644 --- a/testing/web-platform/tests/subresource-integrity/subresource-integrity.html +++ b/testing/web-platform/tests/subresource-integrity/subresource-integrity.html @@ -3,6 +3,7 @@ Subresource Integrity +
@@ -68,12 +69,12 @@ // of executing them one at a time, the style tests are implemented as a // queue that builds up a list of tests, and then executes them one at a // time. - var SRIStyleTest = function(queue, pass, name, href, integrityValue, crossoriginValue) { + var SRIStyleTest = function(queue, pass, name, attrs, customCallback, altPassValue) { this.pass = pass; this.name = "Style: " + name; - this.href = href; - this.integrityValue = integrityValue; - this.crossoriginValue = crossoriginValue; + this.customCallback = customCallback || function () {}; + this.attrs = attrs || {}; + this.passValue = altPassValue || "rgb(255, 255, 0)"; this.test = async_test(this.name); @@ -82,6 +83,7 @@ } SRIStyleTest.prototype.execute = function() { + var that = this; var container = document.getElementById("container"); while (container.hasChildNodes()) { container.removeChild(container.firstChild); @@ -92,17 +94,18 @@ var div = document.createElement("div"); div.className = "testdiv"; var e = document.createElement("link"); - e.rel = "stylesheet"; - e.href = this.href; - e.setAttribute("integrity", this.integrityValue); - if(this.crossoriginValue) { - e.setAttribute("crossorigin", this.crossoriginValue); + this.attrs.rel = this.attrs.rel || "stylesheet"; + for (var key in this.attrs) { + if (this.attrs.hasOwnProperty(key)) { + e.setAttribute(key, this.attrs[key]); + } } + if(this.pass) { e.addEventListener("load", function() { test.step(function() { var background = window.getComputedStyle(div, null).getPropertyValue("background-color"); - assert_equals(background, "rgb(255, 255, 0)"); + assert_equals(background, that.passValue); test.done(); }); }); @@ -123,6 +126,7 @@ } container.appendChild(div); container.appendChild(e); + this.customCallback(e, container); }; var style_tests = []; @@ -281,157 +285,256 @@ style_tests, true, "Same-origin with correct sha256 hash", - "style.css", - "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4=" + { + href: "style.css", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4=" + } ); new SRIStyleTest( style_tests, true, "Same-origin with correct sha384 hash", - "style.css", - "sha384-wDAWxH4tOWBwAwHfBn9B7XuNmFxHTMeigAMwn0iVQ0zq3FtmYMLxihcGnU64CwcX" + { + href: "style.css", + integrity: "sha384-wDAWxH4tOWBwAwHfBn9B7XuNmFxHTMeigAMwn0iVQ0zq3FtmYMLxihcGnU64CwcX" + } ); new SRIStyleTest( style_tests, true, "Same-origin with correct sha512 hash", - "style.css", - "sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w==" + { + href: "style.css", + integrity: "sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w==" + } ); new SRIStyleTest( style_tests, true, "Same-origin with empty integrity", - "style.css", - "" + { + href: "style.css", + integrity: "" + } ); new SRIStyleTest( style_tests, false, "Same-origin with incorrect hash.", - "style.css", - "sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + { + href: "style.css", + integrity: "sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + } ); new SRIStyleTest( style_tests, true, "Same-origin with multiple sha256 hashes, including correct.", - "style.css", - "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4= sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + { + href: "style.css", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4= sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + } ); new SRIStyleTest( style_tests, true, "Same-origin with multiple sha256 hashes, including unknown algorithm.", - "style.css", - "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4= foo666-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + { + href: "style.css", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4= foo666-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + } ); new SRIStyleTest( style_tests, true, "Same-origin with sha256 mismatch, sha512 match", - "style.css", - "sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w== sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + { + href: "style.css", + integrity: "sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w== sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead" + } ); new SRIStyleTest( style_tests, false, "Same-origin with sha256 match, sha512 mismatch", - "style.css", - "sha512-deadbeef9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2== sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4=" + { + href: "style.css", + integrity: "sha512-deadbeef9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2== sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4=" + } ); new SRIStyleTest( style_tests, true, " with correct hash, ACAO: *", - xorigin_anon_style, - "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", - "anonymous" + { + href: xorigin_anon_style, + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", + crossorigin: "anonymous" + } ); new SRIStyleTest( style_tests, false, " with incorrect hash, ACAO: *", - xorigin_anon_style, - "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=", - "anonymous" + { + href: xorigin_anon_style, + integrity: "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=", + crossorigin: "anonymous" + } ); new SRIStyleTest( style_tests, true, " with correct hash, CORS-eligible", - xorigin_creds_style, - "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", - "use-credentials" + { + href: xorigin_creds_style, + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", + crossorigin: "use-credentials" + } ); new SRIStyleTest( style_tests, false, " with incorrect hash CORS-eligible", - xorigin_creds_style, - "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=", - "use-credentials" + { + href: xorigin_creds_style, + integrity: "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=", + crossorigin: "use-credentials" + } ); new SRIStyleTest( style_tests, false, " with CORS-ineligible resource", - xorigin_ineligible_style, - "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", - "anonymous" + { + href: xorigin_ineligible_style, + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=", + crossorigin: "anonymous" + } ); new SRIStyleTest( style_tests, true, "Cross-origin, not CORS request, with correct hash", - xorigin_anon_style, - "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=" + { + href: xorigin_anon_style, + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=" + } ); new SRIStyleTest( style_tests, true, "Cross-origin, not CORS request, with hash masmatch", - xorigin_anon_style, - "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=" + { + href: xorigin_anon_style, + integrity: "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=" + } ); new SRIStyleTest( style_tests, true, "Cross-origin, empty integrity", - xorigin_anon_style, - "" + { + href: xorigin_anon_style, + integrity: "" + } ); new SRIStyleTest( style_tests, true, "Same-origin with correct hash, options.", - "style.css", - "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=?foo=bar?spam=eggs" + { + href: "style.css", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=?foo=bar?spam=eggs" + } ); new SRIStyleTest( style_tests, true, "Same-origin with unknown algorithm only.", - "style.css", - "foo666-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=?foo=bar?spam=eggs" + { + href: "style.css", + integrity: "foo666-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=?foo=bar?spam=eggs" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct sha256 hash, rel='stylesheet license'", + { + href: "style.css", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4=", + rel: "stylesheet license" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct sha256 hash, rel='license stylesheet'", + { + href: "style.css", + integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F-SPLT7YZk7gyCWUV4=", + rel: "license stylesheet" + } + ); + + new SRIStyleTest( + style_tests, + true, + "Same-origin with correct sha256 and sha512 hash, rel='alternate stylesheet' enabled", + { + href: "alternate.css", + title: "alt", + type: "text/css", + class: "alternate", + disabled: "disabled", + rel: "alternate stylesheet", + integrity: "sha256-phbz83bWhnLig+d2VPKrRrTRyhqoDRo1ruGqZLZ0= sha512-8OYEB7ktnzcb6h+kB9CUIuc8qvKIyLpygRJdQSEEycRy74dUsB+Yu9rSjpOPjRUblle8WWX9Gn7v39LK2Oceig==", + }, + function (link, container) { + var alternate = document.querySelector('link.alternate'); + alternate.disabled = false; + }, + "rgb(255, 0, 0)" + ); + + new SRIStyleTest( + style_tests, + false, + "Same-origin with incorrect sha256 and sha512 hash, rel='alternate stylesheet' enabled", + { + href: "alternate.css", + title: "alt", + type: "text/css", + class: "alternate", + disabled: "disabled", + rel: "alternate stylesheet", + integrity: "sha256-fail83bWhnLig+d2VPKrRrTRyhqoDRo1ruGqZLZ0= sha512-failB7ktnzcb6h+kB9CUIuc8qvKIyLpygRJdQSEEycRy74dUsB+Yu9rSjpOPjRUblle8WWX9Gn7v39LK2Oceig==", + }, + function (link, container) { + var alternate = document.querySelector('link.alternate'); + alternate.disabled = false; + } ); style_tests.execute(); diff --git a/testing/web-platform/tests/websockets/interfaces/WebSocket/url/resolve.html b/testing/web-platform/tests/websockets/interfaces/WebSocket/url/resolve.html new file mode 100644 index 00000000000..7708b69c8b6 --- /dev/null +++ b/testing/web-platform/tests/websockets/interfaces/WebSocket/url/resolve.html @@ -0,0 +1,12 @@ + +WebSocket#url: resolving + + + +
+ diff --git a/toolkit/components/places/AsyncFaviconHelpers.cpp b/toolkit/components/places/AsyncFaviconHelpers.cpp index 105b1a05bbc..7b136e447b5 100644 --- a/toolkit/components/places/AsyncFaviconHelpers.cpp +++ b/toolkit/components/places/AsyncFaviconHelpers.cpp @@ -348,7 +348,7 @@ OptimizeIconSize(IconData& aIcon, AsyncFaviconHelperBase::AsyncFaviconHelperBase( nsCOMPtr& aCallback -) : mDB(Database::GetDatabase()) +) { // Don't AddRef or Release in runnables for thread-safety. mCallback.swap(aCallback); @@ -451,7 +451,9 @@ AsyncFetchAndSetIconForPage::Run() "This should not be called on the main thread"); // Try to fetch the icon from the database. - nsresult rv = FetchIconInfo(mDB, mIcon); + nsRefPtr DB = Database::GetDatabase(); + NS_ENSURE_STATE(DB); + nsresult rv = FetchIconInfo(DB, mIcon); NS_ENSURE_SUCCESS(rv, rv); bool isInvalidIcon = mIcon.data.IsEmpty() || @@ -464,7 +466,7 @@ AsyncFetchAndSetIconForPage::Run() // directly proceed with association. nsRefPtr event = new AsyncAssociateIconToPage(mIcon, mPage, mCallback); - mDB->DispatchToAsyncThread(event); + DB->DispatchToAsyncThread(event); return NS_OK; } @@ -695,9 +697,11 @@ AsyncFetchAndSetIconFromNetwork::OnStopRequest(nsIRequest* aRequest, mIcon.status = ICON_STATUS_CHANGED; + nsRefPtr DB = Database::GetDatabase(); + NS_ENSURE_STATE(DB); nsRefPtr event = new AsyncAssociateIconToPage(mIcon, mPage, mCallback); - mDB->DispatchToAsyncThread(event); + DB->DispatchToAsyncThread(event); return NS_OK; } @@ -725,7 +729,9 @@ AsyncAssociateIconToPage::Run() NS_PRECONDITION(!NS_IsMainThread(), "This should not be called on the main thread"); - nsresult rv = FetchPageInfo(mDB, mPage); + nsRefPtr DB = Database::GetDatabase(); + NS_ENSURE_STATE(DB); + nsresult rv = FetchPageInfo(DB, mPage); if (rv == NS_ERROR_NOT_AVAILABLE){ // We have never seen this page. If we can add the page to history, // we will try to do it later, otherwise just bail out. @@ -737,19 +743,19 @@ AsyncAssociateIconToPage::Run() NS_ENSURE_SUCCESS(rv, rv); } - mozStorageTransaction transaction(mDB->MainConn(), false, + mozStorageTransaction transaction(DB->MainConn(), false, mozIStorageConnection::TRANSACTION_IMMEDIATE); // If there is no entry for this icon, or the entry is obsolete, replace it. if (mIcon.id == 0 || (mIcon.status & ICON_STATUS_CHANGED)) { - rv = SetIconInfo(mDB, mIcon); + rv = SetIconInfo(DB, mIcon); NS_ENSURE_SUCCESS(rv, rv); // Get the new icon id. Do this regardless mIcon.id, since other code // could have added a entry before us. Indeed we interrupted the thread // after the previous call to FetchIconInfo. mIcon.status = (mIcon.status & ~(ICON_STATUS_CACHED)) | ICON_STATUS_SAVED; - rv = FetchIconInfo(mDB, mIcon); + rv = FetchIconInfo(DB, mIcon); NS_ENSURE_SUCCESS(rv, rv); } @@ -764,7 +770,7 @@ AsyncAssociateIconToPage::Run() if (mPage.iconId != mIcon.id) { nsCOMPtr stmt; if (mPage.id) { - stmt = mDB->GetStatement( + stmt = DB->GetStatement( "UPDATE moz_places SET favicon_id = :icon_id WHERE id = :page_id" ); NS_ENSURE_STATE(stmt); @@ -772,7 +778,7 @@ AsyncAssociateIconToPage::Run() NS_ENSURE_SUCCESS(rv, rv); } else { - stmt = mDB->GetStatement( + stmt = DB->GetStatement( "UPDATE moz_places SET favicon_id = :icon_id WHERE url = :page_url" ); NS_ENSURE_STATE(stmt); @@ -846,8 +852,10 @@ AsyncGetFaviconURLForPage::Run() NS_PRECONDITION(!NS_IsMainThread(), "This should not be called on the main thread."); + nsRefPtr DB = Database::GetDatabase(); + NS_ENSURE_STATE(DB); nsAutoCString iconSpec; - nsresult rv = FetchIconURL(mDB, mPageSpec, iconSpec); + nsresult rv = FetchIconURL(DB, mPageSpec, iconSpec); NS_ENSURE_SUCCESS(rv, rv); // Now notify our callback of the icon spec we retrieved, even if empty. @@ -911,8 +919,10 @@ AsyncGetFaviconDataForPage::Run() NS_PRECONDITION(!NS_IsMainThread(), "This should not be called on the main thread."); + nsRefPtr DB = Database::GetDatabase(); + NS_ENSURE_STATE(DB); nsAutoCString iconSpec; - nsresult rv = FetchIconURL(mDB, mPageSpec, iconSpec); + nsresult rv = FetchIconURL(DB, mPageSpec, iconSpec); NS_ENSURE_SUCCESS(rv, rv); IconData iconData; @@ -922,7 +932,7 @@ AsyncGetFaviconDataForPage::Run() pageData.spec.Assign(mPageSpec); if (!iconSpec.IsEmpty()) { - rv = FetchIconInfo(mDB, iconData); + rv = FetchIconInfo(DB, iconData); if (NS_FAILED(rv)) { iconData.spec.Truncate(); } @@ -975,16 +985,18 @@ AsyncReplaceFaviconData::Run() NS_PRECONDITION(!NS_IsMainThread(), "This should not be called on the main thread"); + nsRefPtr DB = Database::GetDatabase(); + NS_ENSURE_STATE(DB); IconData dbIcon; dbIcon.spec.Assign(mIcon.spec); - nsresult rv = FetchIconInfo(mDB, dbIcon); + nsresult rv = FetchIconInfo(DB, dbIcon); NS_ENSURE_SUCCESS(rv, rv); if (!dbIcon.id) { return NS_OK; } - rv = SetIconInfo(mDB, mIcon); + rv = SetIconInfo(DB, mIcon); NS_ENSURE_SUCCESS(rv, rv); // We can invalidate the cache version since we now persist the icon. @@ -1096,11 +1108,14 @@ NotifyIconObservers::SendGlobalNotifications(nsIURI* aIconURI) PageData bookmarkedPage; bookmarkedPage.spec = mPage.bookmarkedSpec; + nsRefPtr DB = Database::GetDatabase(); + if (!DB) + return; // This will be silent, so be sure to not pass in the current callback. nsCOMPtr nullCallback; nsRefPtr event = new AsyncAssociateIconToPage(mIcon, bookmarkedPage, nullCallback); - mDB->DispatchToAsyncThread(event); + DB->DispatchToAsyncThread(event); } } diff --git a/toolkit/components/places/AsyncFaviconHelpers.h b/toolkit/components/places/AsyncFaviconHelpers.h index ce988a83338..dae8bfc53cc 100644 --- a/toolkit/components/places/AsyncFaviconHelpers.h +++ b/toolkit/components/places/AsyncFaviconHelpers.h @@ -102,7 +102,6 @@ protected: virtual ~AsyncFaviconHelperBase(); - nsRefPtr mDB; // Strong reference since we are responsible for its existence. nsCOMPtr mCallback; }; diff --git a/toolkit/components/places/Database.cpp b/toolkit/components/places/Database.cpp index 16d8384719a..67832cc227c 100644 --- a/toolkit/components/places/Database.cpp +++ b/toolkit/components/places/Database.cpp @@ -315,8 +315,8 @@ public: * `true` if we have not started shutdown, i.e. if * `BlockShutdown()` hasn't been called yet, false otherwise. */ - bool IsStarted() const { - return mIsStarted; + static bool IsStarted() { + return sIsStarted; } private: @@ -354,21 +354,22 @@ private: NOTIFIED_OBSERVERS_PLACES_CONNECTION_CLOSED, }; State mState; - bool mIsStarted; // As tests may resurrect a dead `Database`, we use a counter to // give the instances of `DatabaseShutdown` unique names. uint16_t mCounter; static uint16_t sCounter; + static Atomic sIsStarted; + ~DatabaseShutdown() {} }; uint16_t DatabaseShutdown::sCounter = 0; +Atomic DatabaseShutdown::sIsStarted(false); DatabaseShutdown::DatabaseShutdown(Database* aDatabase) : mDatabase(aDatabase) , mState(NOT_STARTED) - , mIsStarted(false) , mCounter(sCounter++) { MOZ_ASSERT(NS_IsMainThread()); @@ -465,7 +466,7 @@ DatabaseShutdown::BlockShutdown(nsIAsyncShutdownClient* aParentClient) { mParentClient = aParentClient; mState = RECEIVED_BLOCK_SHUTDOWN; - mIsStarted = true; + sIsStarted = true; if (NS_WARN_IF(!mBarrier)) { return NS_ERROR_NOT_AVAILABLE; @@ -662,6 +663,15 @@ Database::GetConnectionShutdown() return mConnectionShutdown->GetClient(); } +// static +already_AddRefed +Database::GetDatabase() +{ + if (DatabaseShutdown::IsStarted()) + return nullptr; + return GetSingleton(); +} + nsresult Database::Init() { diff --git a/toolkit/components/places/Database.h b/toolkit/components/places/Database.h index 19767247f69..72cdcae03da 100644 --- a/toolkit/components/places/Database.h +++ b/toolkit/components/places/Database.h @@ -94,10 +94,7 @@ public: * * @return Singleton instance of this class. */ - static already_AddRefed GetDatabase() - { - return GetSingleton(); - } + static already_AddRefed GetDatabase(); /** * Returns last known database status. diff --git a/toolkit/components/protobuf/m-c-changes.patch b/toolkit/components/protobuf/m-c-changes.patch index 20a1368a4c2..81c72fbc1a3 100644 --- a/toolkit/components/protobuf/m-c-changes.patch +++ b/toolkit/components/protobuf/m-c-changes.patch @@ -363,3 +363,23 @@ // This is the slow-path case where "length" may be too large to // safely allocate. We read as much as we can into *values // without pre-allocating "length" bytes. +--- a/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h ++++ b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h +@@ -39,16 +39,17 @@ + // streams. Of course, many users will probably want to write their own + // implementations of these interfaces specific to the particular I/O + // abstractions they prefer to use, but these should cover the most common + // cases. + + #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ + #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ + ++#include /* See Bug 1186561 */ + #include + #include + #include + #include + #include + + + namespace google { diff --git a/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h index e18da72ca12..44c6e7727f7 100644 --- a/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -44,6 +44,7 @@ #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ +#include /* See Bug 1186561 */ #include #include #include diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 237f8d180c3..8287e4b0e25 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -7482,7 +7482,7 @@ }, "SSL_PERMANENT_CERT_ERROR_OVERRIDES": { "alert_emails": ["seceng@mozilla.org"], - "expires_in_version": "42", + "expires_in_version": "default", "kind": "exponential", "high": 1024, "n_buckets": 10, diff --git a/toolkit/components/telemetry/TelemetrySend.jsm b/toolkit/components/telemetry/TelemetrySend.jsm index a2801737ddf..4a48862c2f8 100644 --- a/toolkit/components/telemetry/TelemetrySend.jsm +++ b/toolkit/components/telemetry/TelemetrySend.jsm @@ -146,7 +146,6 @@ function gzipCompressString(string) { return observer.buffer; } - this.TelemetrySend = { /** @@ -391,8 +390,12 @@ let SendScheduler = { let pending = TelemetryStorage.getPendingPingList(); let current = TelemetrySendImpl.getUnpersistedPings(); this._log.trace("_doSendTask - pending: " + pending.length + ", current: " + current.length); - pending = pending.filter(p => TelemetrySendImpl.sendingEnabled(p)); - current = current.filter(p => TelemetrySendImpl.sendingEnabled(p)); + // Note that the two lists contain different kind of data. |pending| only holds ping + // info, while |current| holds actual ping data. + if (!TelemetrySendImpl.sendingEnabled()) { + pending = pending.filter(pingInfo => TelemetryStorage.isDeletionPing(pingInfo.id)); + current = current.filter(p => isDeletionPing(p)); + } this._log.trace("_doSendTask - can send - pending: " + pending.length + ", current: " + current.length); // Bail out if there is nothing to send. @@ -712,7 +715,12 @@ let TelemetrySendImpl = { yield this._doPing(ping, ping.id, false); } catch (ex) { this._log.info("sendPings - ping " + ping.id + " not sent, saving to disk", ex); - yield TelemetryStorage.savePendingPing(ping); + // Deletion pings must be saved to a special location. + if (isDeletionPing(ping)) { + yield TelemetryStorage.saveDeletionPing(ping); + } else { + yield TelemetryStorage.savePendingPing(ping); + } } finally { this._currentPings.delete(ping.id); } @@ -784,6 +792,9 @@ let TelemetrySendImpl = { } if (success && isPersisted) { + if (TelemetryStorage.isDeletionPing(id)) { + return TelemetryStorage.removeDeletionPing(); + } return TelemetryStorage.removePendingPing(id); } else { return Promise.resolve(); diff --git a/toolkit/components/telemetry/TelemetryStorage.jsm b/toolkit/components/telemetry/TelemetryStorage.jsm index cff79f23906..eda22563f0f 100644 --- a/toolkit/components/telemetry/TelemetryStorage.jsm +++ b/toolkit/components/telemetry/TelemetryStorage.jsm @@ -34,6 +34,7 @@ const Utils = TelemetryUtils; const DATAREPORTING_DIR = "datareporting"; const PINGS_ARCHIVE_DIR = "archived"; const ABORTED_SESSION_FILE_NAME = "aborted-session-ping"; +const DELETION_PING_FILE_NAME = "pending-deletion-ping"; XPCOMUtils.defineLazyGetter(this, "gDataReportingDir", function() { return OS.Path.join(OS.Constants.Path.profileDir, DATAREPORTING_DIR); @@ -44,6 +45,9 @@ XPCOMUtils.defineLazyGetter(this, "gPingsArchivePath", function() { XPCOMUtils.defineLazyGetter(this, "gAbortedSessionFilePath", function() { return OS.Path.join(gDataReportingDir, ABORTED_SESSION_FILE_NAME); }); +XPCOMUtils.defineLazyGetter(this, "gDeletionPingFilePath", function() { + return OS.Path.join(gDataReportingDir, DELETION_PING_FILE_NAME); +}); // Maxmimum time, in milliseconds, archive pings should be retained. const MAX_ARCHIVED_PINGS_RETENTION_MS = 180 * 24 * 60 * 60 * 1000; // 180 days @@ -262,6 +266,30 @@ this.TelemetryStorage = { return TelemetryStorageImpl.loadAbortedSessionPing(); }, + /** + * Save the deletion ping. + * @param ping The deletion ping. + * @return {Promise} A promise resolved when the ping is saved. + */ + saveDeletionPing: function(ping) { + return TelemetryStorageImpl.saveDeletionPing(ping); + }, + + /** + * Remove the deletion ping. + * @return {Promise} Resolved when the ping is deleted from the disk. + */ + removeDeletionPing: function() { + return TelemetryStorageImpl.removeDeletionPing(); + }, + + /** + * Check if the ping id identifies a deletion ping. + */ + isDeletionPing: function(aPingId) { + return TelemetryStorageImpl.isDeletionPing(aPingId); + }, + /** * Remove the aborted-session ping if present. * @@ -482,6 +510,8 @@ let TelemetryStorageImpl = { _logger: null, // Used to serialize aborted session ping writes to disk. _abortedSessionSerializer: new SaveSerializer(), + // Used to serialize deletion ping writes to disk. + _deletionPingSerializer: new SaveSerializer(), // Tracks the archived pings in a Map of (id -> {timestampCreated, type}). // We use this to cache info on archived pings to avoid scanning the disk more than once. @@ -521,6 +551,7 @@ let TelemetryStorageImpl = { shutdown: Task.async(function*() { this._shutdown = true; yield this._abortedSessionSerializer.flushTasks(); + yield this._deletionPingSerializer.flushTasks(); // If the tasks for archive cleaning or pending ping quota are still running, block on // them. They will bail out as soon as possible. yield this._cleanArchiveTask; @@ -1225,6 +1256,18 @@ let TelemetryStorageImpl = { } yield iter.close(); + + // Explicitly load the deletion ping from its known path, if it's there. + if (yield OS.File.exists(gDeletionPingFilePath)) { + this._log.trace("_scanPendingPings - Adding pending deletion ping."); + // We can't get the ping id or the last modification date without hitting the disk. + // Since deletion has a special handling, we don't really need those. + this._pendingPings.set(Utils.generateUUID(), { + path: gDeletionPingFilePath, + lastModificationDate: Date.now(), + }); + } + this._scannedPendingDirectory = true; return this._buildPingList(); }), @@ -1379,6 +1422,50 @@ let TelemetryStorageImpl = { } }.bind(this))); }, + + /** + * Save the deletion ping. + * @param ping The deletion ping. + * @return {Promise} Resolved when the ping is saved. + */ + saveDeletionPing: Task.async(function*(ping) { + this._log.trace("saveDeletionPing - ping path: " + gDeletionPingFilePath); + yield OS.File.makeDir(gDataReportingDir, { ignoreExisting: true }); + + return this._deletionPingSerializer.enqueueTask(() => + this.savePingToFile(ping, gDeletionPingFilePath, true)); + }), + + /** + * Remove the deletion ping. + * @return {Promise} Resolved when the ping is deleted from the disk. + */ + removeDeletionPing: Task.async(function*() { + return this._deletionPingSerializer.enqueueTask(Task.async(function*() { + try { + yield OS.File.remove(gDeletionPingFilePath, { ignoreAbsent: false }); + this._log.trace("removeDeletionPing - success"); + } catch (ex if ex.becauseNoSuchFile) { + this._log.trace("removeDeletionPing - no such file"); + } catch (ex) { + this._log.error("removeDeletionPing - error removing ping", ex) + } + }.bind(this))); + }), + + isDeletionPing: function(aPingId) { + this._log.trace("isDeletionPing - id: " + aPingId); + let pingInfo = this._pendingPings.get(aPingId); + if (!pingInfo) { + return false; + } + + if (pingInfo.path != gDeletionPingFilePath) { + return false; + } + + return true; + }, }; ///// Utility functions diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetryController.js b/toolkit/components/telemetry/tests/unit/test_TelemetryController.js index b4a27e98932..2378e0f340f 100644 --- a/toolkit/components/telemetry/tests/unit/test_TelemetryController.js +++ b/toolkit/components/telemetry/tests/unit/test_TelemetryController.js @@ -152,11 +152,37 @@ add_task(function* test_deletionPing() { return; } + const PREF_TELEMETRY_SERVER = "toolkit.telemetry.server"; + // Disable FHR upload: this should trigger a deletion ping. Preferences.set(PREF_FHR_UPLOAD_ENABLED, false); let ping = yield PingServer.promiseNextPing(); checkPingFormat(ping, DELETION_PING_TYPE, true, false); + // Wait on ping activity to settle. + yield TelemetrySend.testWaitOnOutgoingPings(); + + // Restore FHR Upload. + Preferences.set(PREF_FHR_UPLOAD_ENABLED, true); + + // Simulate a failure in sending the deletion ping by disabling the HTTP server. + yield PingServer.stop(); + // Disable FHR upload to send a deletion ping again. + Preferences.set(PREF_FHR_UPLOAD_ENABLED, false); + // Wait for the send task to terminate, flagging it to do so at the next opportunity and + // cancelling any timeouts. + yield TelemetryController.reset(); + + // Enable the ping server again. + PingServer.start(); + // We set the new server using the pref, otherwise it would get reset with + // |TelemetryController.reset|. + Preferences.set(PREF_TELEMETRY_SERVER, "http://localhost:" + PingServer.port); + + // Reset the controller to spin the ping sending task. + yield TelemetryController.reset(); + ping = yield PingServer.promiseNextPing(); + checkPingFormat(ping, DELETION_PING_TYPE, true, false); // Restore FHR Upload. Preferences.set(PREF_FHR_UPLOAD_ENABLED, true); @@ -262,7 +288,7 @@ add_task(function* test_archivePings() { add_task(function* test_midnightPingSendFuzzing() { const fuzzingDelay = 60 * 60 * 1000; fakeMidnightPingFuzzingDelay(fuzzingDelay); - let now = new Date(2030, 5, 1, 11, 00, 0); + let now = new Date(2030, 5, 1, 11, 0, 0); fakeNow(now); let waitForTimer = () => new Promise(resolve => { diff --git a/toolkit/components/url-classifier/PrivateBrowsingTrackingProtectionWhitelist.js b/toolkit/components/url-classifier/PrivateBrowsingTrackingProtectionWhitelist.js new file mode 100644 index 00000000000..5c1c27874d4 --- /dev/null +++ b/toolkit/components/url-classifier/PrivateBrowsingTrackingProtectionWhitelist.js @@ -0,0 +1,68 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +function PrivateBrowsingTrackingProtectionWhitelist() { + // The list of URIs explicitly excluded from tracking protection. + this._allowlist = []; + + Services.obs.addObserver(this, "last-pb-context-exited", true); +} + +PrivateBrowsingTrackingProtectionWhitelist.prototype = { + classID: Components.ID("{a319b616-c45d-4037-8d86-01c592b5a9af}"), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrivateBrowsingTrackingProtectionWhitelist, + Ci.nsIObserver, + Ci.nsISupportsWeakReference, + Ci.nsISupports]), + _xpcom_factory: XPCOMUtils.generateSingletonFactory(PrivateBrowsingTrackingProtectionWhitelist), + + /** + * Add the provided URI to the list of allowed tracking sites. + * + * @param uri nsIURI + * The URI to add to the list. + */ + addToAllowList(uri) { + if (this._allowlist.indexOf(uri.spec) === -1) { + this._allowlist.push(uri.spec); + } + }, + + /** + * Remove the provided URI from the list of allowed tracking sites. + * + * @param uri nsIURI + * The URI to add to the list. + */ + removeFromAllowList(uri) { + let index = this._allowlist.indexOf(uri.spec); + if (index !== -1) { + this._allowlist.splice(index, 1); + } + }, + + /** + * Check if the provided URI exists in the list of allowed tracking sites. + * + * @param uri nsIURI + * The URI to add to the list. + */ + existsInAllowList(uri) { + return this._allowlist.indexOf(uri.spec) !== -1; + }, + + observe: function (subject, topic, data) { + if (topic == "last-pb-context-exited") { + this._allowlist = []; + } + } +}; + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PrivateBrowsingTrackingProtectionWhitelist]); diff --git a/toolkit/components/url-classifier/moz.build b/toolkit/components/url-classifier/moz.build index 169de362426..22a48caea39 100644 --- a/toolkit/components/url-classifier/moz.build +++ b/toolkit/components/url-classifier/moz.build @@ -7,6 +7,7 @@ TEST_DIRS += ['tests'] XPIDL_SOURCES += [ + 'nsIPrivateBrowsingTrackingProtectionWhitelist.idl', 'nsIUrlClassifierDBService.idl', 'nsIUrlClassifierHashCompleter.idl', 'nsIUrlClassifierPrefixSet.idl', @@ -42,6 +43,7 @@ SOURCES += [ EXTRA_COMPONENTS += [ 'nsURLClassifier.manifest', 'nsUrlClassifierHashCompleter.js', + 'PrivateBrowsingTrackingProtectionWhitelist.js', ] # Same as JS components that are run through the pre-processor. diff --git a/toolkit/components/url-classifier/nsIPrivateBrowsingTrackingProtectionWhitelist.idl b/toolkit/components/url-classifier/nsIPrivateBrowsingTrackingProtectionWhitelist.idl new file mode 100644 index 00000000000..c3621ce233f --- /dev/null +++ b/toolkit/components/url-classifier/nsIPrivateBrowsingTrackingProtectionWhitelist.idl @@ -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 http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIURI; + +/** + * The Private Browsing Tracking Protection service checks a URI against an + * in-memory list of tracking sites. + */ +[scriptable, uuid(c77ddfac-6cd6-43a9-84e8-91682a1a7b18)] +interface nsIPrivateBrowsingTrackingProtectionWhitelist : nsISupports +{ + /** + * Add a URI to the list of allowed tracking sites in Private Browsing mode + * (essentially a tracking whitelist). This operation will cause the URI to + * be registered if it does not currently exist. If it already exists, then + * the operation is essentially a no-op. + * + * @param uri the uri to add to the list + */ + void addToAllowList(in nsIURI uri); + + /** + * Remove a URI from the list of allowed tracking sites in Private Browsing + * mode (the tracking whitelist). If the URI is not already in the list, + * then the operation is essentially a no-op. + * + * @param uri the uri to remove from the list + */ + void removeFromAllowList(in nsIURI uri); + + /** + * Check if a URI exists in the list of allowed tracking sites in Private + * Browsing mode (the tracking whitelist). + * + * @param uri the uri to look for in the list + */ + bool existsInAllowList(in nsIURI uri); +}; + +%{ C++ +#define NS_PBTRACKINGPROTECTIONWHITELIST_CONTRACTID "@mozilla.org/url-classifier/pbm-tp-whitelist;1" +%} diff --git a/toolkit/components/url-classifier/nsURLClassifier.manifest b/toolkit/components/url-classifier/nsURLClassifier.manifest index f035dea8095..fa5e41d4554 100644 --- a/toolkit/components/url-classifier/nsURLClassifier.manifest +++ b/toolkit/components/url-classifier/nsURLClassifier.manifest @@ -4,3 +4,5 @@ component {ca168834-cc00-48f9-b83c-fd018e58cae3} nsUrlClassifierListManager.js contract @mozilla.org/url-classifier/listmanager;1 {ca168834-cc00-48f9-b83c-fd018e58cae3} component {9111de73-9322-4bfc-8b65-2b727f3e6ec8} nsUrlClassifierHashCompleter.js contract @mozilla.org/url-classifier/hashcompleter;1 {9111de73-9322-4bfc-8b65-2b727f3e6ec8} +component {a319b616-c45d-4037-8d86-01c592b5a9af} PrivateBrowsingTrackingProtectionWhitelist.js +contract @mozilla.org/url-classifier/pbm-tp-whitelist;1 {a319b616-c45d-4037-8d86-01c592b5a9af} diff --git a/toolkit/content/process-content.js b/toolkit/content/process-content.js index 78aaa1adad5..148522ecbcc 100644 --- a/toolkit/content/process-content.js +++ b/toolkit/content/process-content.js @@ -10,3 +10,6 @@ let { classes: Cc, interfaces: Ci, utils: Cu } = Components; // and for those that match URLs provided by the parent process will set up // a dedicated message port and notify the parent process. Cu.import("resource://gre/modules/RemotePageManager.jsm"); + +// Hooks to listen for push messages +Cu.import("resource://gre/modules/PushServiceChildPreload.jsm"); diff --git a/toolkit/devtools/server/actors/utils/make-debugger.js b/toolkit/devtools/server/actors/utils/make-debugger.js index 5e6b7c10ffa..968aa293418 100644 --- a/toolkit/devtools/server/actors/utils/make-debugger.js +++ b/toolkit/devtools/server/actors/utils/make-debugger.js @@ -68,15 +68,15 @@ module.exports = function makeDebugger({ findDebuggees, shouldAddNewGlobalAsDebu dbg.uncaughtExceptionHook = reportDebuggerHookException; - dbg.onNewGlobalObject = global => { + dbg.onNewGlobalObject = function(global) { if (shouldAddNewGlobalAsDebuggee(global)) { - safeAddDebuggee(dbg, global); + safeAddDebuggee(this, global); } }; - dbg.addDebuggees = () => { - for (let global of findDebuggees(dbg)) { - safeAddDebuggee(dbg, global); + dbg.addDebuggees = function() { + for (let global of findDebuggees(this)) { + safeAddDebuggee(this, global); } }; diff --git a/toolkit/modules/PrivateBrowsingUtils.jsm b/toolkit/modules/PrivateBrowsingUtils.jsm index f322347fa38..8eec35dd780 100644 --- a/toolkit/modules/PrivateBrowsingUtils.jsm +++ b/toolkit/modules/PrivateBrowsingUtils.jsm @@ -51,6 +51,18 @@ this.PrivateBrowsingUtils = { .QueryInterface(Ci.nsILoadContext); }, + addToTrackingAllowlist(aURI) { + let pbmtpWhitelist = Cc["@mozilla.org/url-classifier/pbm-tp-whitelist;1"] + .getService(Ci.nsIPrivateBrowsingTrackingProtectionWhitelist); + pbmtpWhitelist.addToAllowList(aURI); + }, + + removeFromTrackingAllowlist(aURI) { + let pbmtpWhitelist = Cc["@mozilla.org/url-classifier/pbm-tp-whitelist;1"] + .getService(Ci.nsIPrivateBrowsingTrackingProtectionWhitelist); + pbmtpWhitelist.removeFromAllowList(aURI); + }, + get permanentPrivateBrowsing() { try { return gTemporaryAutoStartMode || diff --git a/toolkit/mozapps/extensions/amWebInstallListener.js b/toolkit/mozapps/extensions/amWebInstallListener.js index 4857db05850..171f7437619 100644 --- a/toolkit/mozapps/extensions/amWebInstallListener.js +++ b/toolkit/mozapps/extensions/amWebInstallListener.js @@ -119,8 +119,8 @@ Installer.prototype = { if (install.linkedInstalls) { install.linkedInstalls.forEach(function(aInstall) { aInstall.addListener(this); - // App disabled items are not compatible and so fail to install - if (aInstall.addon.appDisabled) + // Corrupt or incompatible items fail to install + if (aInstall.state == AddonManager.STATE_DOWNLOAD_FAILED || aInstall.addon.appDisabled) failed.push(aInstall); else installs.push(aInstall); @@ -132,7 +132,7 @@ Installer.prototype = { break; default: logger.warn("Download of " + install.sourceURI.spec + " in unexpected state " + - install.state); + install.state); } } diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm index c2ddc845f4b..d363960abca 100644 --- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm @@ -5126,7 +5126,7 @@ AddonInstall.prototype = { } let self = this; - this.loadManifest().then(() => { + this.loadManifest(this.file).then(() => { XPIDatabase.getVisibleAddonForID(self.addon.id, function initLocalInstall_getVisibleAddon(aAddon) { self.existingAddon = aAddon; if (aAddon) @@ -5162,6 +5162,10 @@ AddonInstall.prototype = { logger.warn("Invalid XPI", message); this.state = AddonManager.STATE_DOWNLOAD_FAILED; this.error = error; + AddonManagerPrivate.callInstallListeners("onNewInstall", + self.listeners, + self.wrapper); + aCallback(this); }); }, @@ -5337,6 +5341,45 @@ AddonInstall.prototype = { this.addon.releaseNotesURI = this.releaseNotesURI.spec; }, + /** + * Fills out linkedInstalls with AddonInstall instances for the other files + * in a multi-package XPI. + * + * @param aFiles + * An array of { entryName, file } for each remaining file from the + * multi-package XPI. + */ + _createLinkedInstalls: Task.async(function* AI_createLinkedInstalls(aFiles) { + if (aFiles.length == 0) + return; + + // Create new AddonInstall instances for every remaining file + if (!this.linkedInstalls) + this.linkedInstalls = []; + + for (let { entryName, file } of aFiles) { + logger.debug("Creating linked install from " + entryName); + let install = yield new Promise(resolve => AddonInstall.createInstall(resolve, file)); + + // Make the new install own its temporary file + install.ownsTempFile = true; + + this.linkedInstalls.push(install); + + // If one of the internal XPIs was multipackage then move its linked + // installs to the outer install + if (install.linkedInstalls) { + this.linkedInstalls.push(...install.linkedInstalls); + install.linkedInstalls = null; + } + + install.sourceURI = this.sourceURI; + install.releaseNotesURI = this.releaseNotesURI; + if (install.state != AddonManager.STATE_DOWNLOAD_FAILED) + install.updateAddonURIs(); + } + }), + /** * Loads add-on manifests from a multi-package XPI file. Each of the * XPI and JAR files contained in the XPI will be extracted. Any that @@ -5347,97 +5390,58 @@ AddonInstall.prototype = { * @param aZipReader * An open nsIZipReader for the multi-package XPI's files. This will * be closed before this method returns. - * @param aCallback - * A function to call when all of the add-on manifests have been - * loaded. Because this loadMultipackageManifests is an internal API - * we don't exception-wrap this callback */ _loadMultipackageManifests: Task.async(function* AI_loadMultipackageManifests(aZipReader) { let files = []; let entries = aZipReader.findEntries("(*.[Xx][Pp][Ii]|*.[Jj][Aa][Rr])"); while (entries.hasMore()) { let entryName = entries.getNext(); - var target = getTemporaryFile(); + let file = getTemporaryFile(); try { - aZipReader.extract(entryName, target); - files.push(target); + aZipReader.extract(entryName, file); + files.push({ entryName, file }); } catch (e) { logger.warn("Failed to extract " + entryName + " from multi-package " + "XPI", e); - target.remove(false); + file.remove(false); } } aZipReader.close(); if (files.length == 0) { - throw new Error("Multi-package XPI does not contain any packages " + - "to install"); + return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, + "Multi-package XPI does not contain any packages to install"]); } let addon = null; - // Find the first file that has a valid install manifest and use it for + // Find the first file that is a valid install and use it for // the add-on that this AddonInstall instance will install. - while (files.length > 0) { + for (let { entryName, file } of files) { this.removeTemporaryFile(); - this.file = files.shift(); - this.ownsTempFile = true; try { - addon = yield loadManifestFromZipFile(this.file); - break; + yield this.loadManifest(file); + logger.debug("Base multi-package XPI install came from " + entryName); + this.file = file; + this.ownsTempFile = true; + + yield this._createLinkedInstalls(files.filter(f => f.file != file)); + return; } catch (e) { - logger.warn(this.file.leafName + " cannot be installed from multi-package " + - "XPI", e); + // _createLinkedInstalls will log errors when it tries to process this + // file } } - if (!addon) { - // No valid add-on was found - return; - } + // No valid add-on was found, delete all the temporary files + for (let { file } of files) + file.remove(true); - this.addon = addon; - - this.updateAddonURIs(); - - this.addon._install = this; - this.name = this.addon.selectedLocale.name; - this.type = this.addon.type; - this.version = this.addon.version; - - // Setting the iconURL to something inside the XPI locks the XPI and - // makes it impossible to delete on Windows. - //let newIcon = createWrapper(this.addon).iconURL; - //if (newIcon) - // this.iconURL = newIcon; - - // Create new AddonInstall instances for every remaining file - if (files.length > 0) { - this.linkedInstalls = []; - let self = this; - for (let file of files) { - let install = yield new Promise(resolve => AddonInstall.createInstall(resolve, file)); - - // Ignore bad add-ons (createInstall will have logged the error) - if (install.state == AddonManager.STATE_DOWNLOAD_FAILED) { - // Manually remove the temporary file - file.remove(true); - } - else { - // Make the new install own its temporary file - install.ownsTempFile = true; - - self.linkedInstalls.push(install) - - install.sourceURI = self.sourceURI; - install.releaseNotesURI = self.releaseNotesURI; - install.updateAddonURIs(); - } - } - } + return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, + "Multi-package XPI does not contain any valid packages to install"]); }), /** @@ -5449,11 +5453,11 @@ AddonInstall.prototype = { * @throws if the add-on does not contain a valid install manifest or the * XPI is incorrectly signed */ - loadManifest: Task.async(function* AI_loadManifest() { + loadManifest: Task.async(function* AI_loadManifest(file) { let zipreader = Cc["@mozilla.org/libjar/zip-reader;1"]. createInstance(Ci.nsIZipReader); try { - zipreader.open(this.file); + zipreader.open(file); } catch (e) { zipreader.close(); @@ -5771,7 +5775,7 @@ AddonInstall.prototype = { } let self = this; - this.loadManifest().then(() => { + this.loadManifest(this.file).then(() => { if (self.addon.isCompatible) { self.downloadCompleted(); } @@ -5860,9 +5864,10 @@ AddonInstall.prototype = { self.install(); if (self.linkedInstalls) { - self.linkedInstalls.forEach(function(aInstall) { - aInstall.install(); - }); + for (let install of self.linkedInstalls) { + if (install.state == AddonManager.STATE_DOWNLOADED) + install.install(); + } } } }); diff --git a/toolkit/mozapps/extensions/test/addons/test_install7/addon1.xpi b/toolkit/mozapps/extensions/test/addons/test_install7/addon1.xpi new file mode 100644 index 00000000000..9c283d1d428 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install7/addon1.xpi @@ -0,0 +1 @@ +This isn't a valid zip file. \ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/addons/test_install7/addon2.xpi b/toolkit/mozapps/extensions/test/addons/test_install7/addon2.xpi new file mode 100644 index 00000000000..9c283d1d428 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install7/addon2.xpi @@ -0,0 +1 @@ +This isn't a valid zip file. \ No newline at end of file diff --git a/toolkit/mozapps/extensions/test/addons/test_install7/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install7/install.rdf new file mode 100644 index 00000000000..5e99ae29ae1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install7/install.rdf @@ -0,0 +1,10 @@ + + + + + + + 32 + + diff --git a/toolkit/mozapps/extensions/test/addons/test_install8/install.rdf b/toolkit/mozapps/extensions/test/addons/test_install8/install.rdf new file mode 100644 index 00000000000..5e99ae29ae1 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_install8/install.rdf @@ -0,0 +1,10 @@ + + + + + + + 32 + + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_badid.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_badid.xpi new file mode 100644 index 00000000000..6e23eb214c8 Binary files /dev/null and b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_badid.xpi differ diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_broken.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_broken.xpi new file mode 100644 index 00000000000..0ba0f30d1ac Binary files /dev/null and b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_broken.xpi differ diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_signed.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_signed.xpi new file mode 100644 index 00000000000..33101f63c06 Binary files /dev/null and b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_signed.xpi differ diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_unsigned.xpi b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_unsigned.xpi new file mode 100644 index 00000000000..3146870d86b Binary files /dev/null and b/toolkit/mozapps/extensions/test/xpcshell/data/signing_checks/multi_unsigned.xpi differ diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml index b3719a6e7ab..7494591b260 100755 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_gfxBlacklist_AllOS.xml @@ -132,6 +132,32 @@ BLOCKED_DRIVER_VERSION + + All + 0xabcd + + + 0x2783 + 0x1234 + 0x2782 + + WEBRTC_HW_ACCELERATION_ENCODE + BLOCKED_DRIVER_VERSION + + + + All + 0xabcd + + + 0x2783 + 0x1234 + 0x2782 + + WEBRTC_HW_ACCELERATION_DECODE + BLOCKED_DRIVER_VERSION + + All 0xabcd diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js index d8dac6ee9f8..f2787234f06 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js +++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js @@ -1108,9 +1108,13 @@ const AddonListener = { const InstallListener = { onNewInstall: function(install) { if (install.state != AddonManager.STATE_DOWNLOADED && + install.state != AddonManager.STATE_DOWNLOAD_FAILED && install.state != AddonManager.STATE_AVAILABLE) do_throw("Bad install state " + install.state); - do_check_eq(install.error, 0); + if (install.state != AddonManager.STATE_DOWNLOAD_FAILED) + do_check_eq(install.error, 0); + else + do_check_neq(install.error, 0); do_check_eq("onNewInstall", getExpectedInstall()); return check_test_completed(arguments); }, diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js index 2f749e8a999..1a6c4457542 100755 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Version.js @@ -107,6 +107,12 @@ function run_test() { status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBRTC_HW_ACCELERATION); do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBRTC_HW_ACCELERATION_ENCODE); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_WEBRTC_HW_ACCELERATION_DECODE); + do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); + status = gfxInfo.getFeatureStatus(Ci.nsIGfxInfo.FEATURE_DIRECT3D_11_LAYERS); do_check_eq(status, Ci.nsIGfxInfo.FEATURE_STATUS_OK); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_install.js index 16db604c540..18fd17e8153 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_install.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js @@ -647,6 +647,8 @@ function check_test_10(install) { // correct sourceURI. function run_test_11() { prepare_test({ }, [ + "onNewInstall", + "onNewInstall", "onNewInstall", "onNewInstall", "onNewInstall", @@ -657,11 +659,22 @@ function run_test_11() { ensure_test_completed(); do_check_neq(install, null); do_check_neq(install.linkedInstalls, null); - do_check_eq(install.linkedInstalls.length, 3); + do_check_eq(install.linkedInstalls.length, 5); // Might be in any order so sort them based on ID let installs = [install].concat(install.linkedInstalls); installs.sort(function(a, b) { + if (a.state != b.state) { + if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) + return 1; + else if (b.state == AddonManager.STATE_DOWNLOAD_FAILED) + return -1; + } + + // Don't care what order the failed installs show up in + if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) + return 0; + if (a.addon.id < b.addon.id) return -1; if (a.addon.id > b.addon.id) @@ -709,6 +722,12 @@ function run_test_11() { do_check_true(hasFlag(installs[3].addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_INSTALL)); + do_check_eq(installs[4].state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(installs[4].error, AddonManager.ERROR_CORRUPT_FILE); + + do_check_eq(installs[5].state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(installs[5].error, AddonManager.ERROR_CORRUPT_FILE); + AddonManager.getAllInstalls(function(aInstalls) { do_check_eq(aInstalls.length, 4); @@ -815,6 +834,8 @@ function run_test_12() { "onNewInstall", "onNewInstall", "onNewInstall", + "onNewInstall", + "onNewInstall", "onDownloadEnded" ], "addon4@tests.mozilla.org": [ @@ -839,11 +860,22 @@ function run_test_12() { } function check_test_12() { - do_check_eq(gInstall.linkedInstalls.length, 3); + do_check_eq(gInstall.linkedInstalls.length, 5); // Might be in any order so sort them based on ID let installs = [gInstall].concat(gInstall.linkedInstalls); installs.sort(function(a, b) { + if (a.state != b.state) { + if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) + return 1; + else if (b.state == AddonManager.STATE_DOWNLOAD_FAILED) + return -1; + } + + // Don't care what order the failed installs show up in + if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) + return 0; + if (a.addon.id < b.addon.id) return -1; if (a.addon.id > b.addon.id) @@ -883,6 +915,12 @@ function check_test_12() { do_check_eq(installs[3].name, "Multi Test 4"); do_check_eq(installs[3].state, AddonManager.STATE_INSTALLED); + do_check_eq(installs[4].state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(installs[4].error, AddonManager.ERROR_CORRUPT_FILE); + + do_check_eq(installs[5].state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(installs[5].error, AddonManager.ERROR_CORRUPT_FILE); + restartManager(); AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", @@ -1755,7 +1793,45 @@ function check_test_29(install) { prepare_test({}, [ "onDownloadCancelled" - ], do_test_finished); + ], run_test_30); install.cancel(); return false; } + +// Tests that a multi-package XPI with no add-ons inside shows up as a +// corrupt file +function run_test_30() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_install7"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); + do_check_eq(install.linkedInstalls, null); + + run_test_31(); + }); +} + +// Tests that a multi-package XPI with no valid add-ons inside shows up as a +// corrupt file +function run_test_31() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_install8"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); + do_check_eq(install.linkedInstalls, null); + + end_test(); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js index 0c7003d59ab..d1977456bcb 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js @@ -636,6 +636,8 @@ function check_test_10(install) { // correct sourceURI. function run_test_11() { prepare_test({ }, [ + "onNewInstall", + "onNewInstall", "onNewInstall", "onNewInstall", "onNewInstall", @@ -646,11 +648,22 @@ function run_test_11() { ensure_test_completed(); do_check_neq(install, null); do_check_neq(install.linkedInstalls, null); - do_check_eq(install.linkedInstalls.length, 3); + do_check_eq(install.linkedInstalls.length, 5); // Might be in any order so sort them based on ID let installs = [install].concat(install.linkedInstalls); installs.sort(function(a, b) { + if (a.state != b.state) { + if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) + return 1; + else if (b.state == AddonManager.STATE_DOWNLOAD_FAILED) + return -1; + } + + // Don't care what order the failed installs show up in + if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) + return 0; + if (a.addon.id < b.addon.id) return -1; if (a.addon.id > b.addon.id) @@ -698,6 +711,12 @@ function run_test_11() { do_check_true(hasFlag(installs[3].addon.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_INSTALL)); + do_check_eq(installs[4].state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(installs[4].error, AddonManager.ERROR_CORRUPT_FILE); + + do_check_eq(installs[5].state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(installs[5].error, AddonManager.ERROR_CORRUPT_FILE); + AddonManager.getAllInstalls(function(aInstalls) { do_check_eq(aInstalls.length, 4); @@ -806,6 +825,8 @@ function run_test_12() { "onNewInstall", "onNewInstall", "onNewInstall", + "onNewInstall", + "onNewInstall", "onDownloadEnded" ], "addon4@tests.mozilla.org": [ @@ -830,11 +851,22 @@ function run_test_12() { } function check_test_12() { - do_check_eq(gInstall.linkedInstalls.length, 3); + do_check_eq(gInstall.linkedInstalls.length, 5); // Might be in any order so sort them based on ID let installs = [gInstall].concat(gInstall.linkedInstalls); installs.sort(function(a, b) { + if (a.state != b.state) { + if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) + return 1; + else if (b.state == AddonManager.STATE_DOWNLOAD_FAILED) + return -1; + } + + // Don't care what order the failed installs show up in + if (a.state == AddonManager.STATE_DOWNLOAD_FAILED) + return 0; + if (a.addon.id < b.addon.id) return -1; if (a.addon.id > b.addon.id) @@ -874,6 +906,12 @@ function check_test_12() { do_check_eq(installs[3].name, "Multi Test 4"); do_check_eq(installs[3].state, AddonManager.STATE_INSTALLED); + do_check_eq(installs[4].state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(installs[4].error, AddonManager.ERROR_CORRUPT_FILE); + + do_check_eq(installs[5].state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(installs[5].error, AddonManager.ERROR_CORRUPT_FILE); + restartManager(); AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org", @@ -1650,5 +1688,43 @@ function finish_test_27(aInstall) { ensure_test_completed(); - end_test(); + run_test_30(); +} + +// Tests that a multi-package XPI with no add-ons inside shows up as a +// corrupt file +function run_test_30() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_install7"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); + do_check_eq(install.linkedInstalls, null); + + run_test_31(); + }); +} + +// Tests that a multi-package XPI with no valid add-ons inside shows up as a +// corrupt file +function run_test_31() { + prepare_test({ }, [ + "onNewInstall" + ]); + + AddonManager.getInstallForFile(do_get_addon("test_install8"), function(install) { + ensure_test_completed(); + + do_check_neq(install, null); + do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED); + do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE); + do_check_eq(install.linkedInstalls, null); + + end_test(); + }); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_signed_multi.js b/toolkit/mozapps/extensions/test/xpcshell/test_signed_multi.js new file mode 100644 index 00000000000..f77279d0df8 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_signed_multi.js @@ -0,0 +1,55 @@ +// Enable signature checks for these tests +Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true); +// Disable update security +Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); + +const DATA = "data/signing_checks/"; + +// Each multi-package XPI contains one valid theme and one other add-on that +// has the following error state: +const ADDONS = { + "multi_signed.xpi": 0, + "multi_badid.xpi": AddonManager.ERROR_CORRUPT_FILE, + "multi_broken.xpi": AddonManager.ERROR_CORRUPT_FILE, + "multi_unsigned.xpi": AddonManager.ERROR_SIGNEDSTATE_REQUIRED, +}; + +function createInstall(filename) { + return new Promise(resolve => { + AddonManager.getInstallForFile(do_get_file(DATA + filename), resolve, "application/x-xpinstall"); + }); +} + +function run_test() { + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "4", "4"); + startupManager(); + + run_next_test(); +} + +function* test_addon(filename) { + do_print("Testing " + filename); + + let install = yield createInstall(filename); + do_check_eq(install.state, AddonManager.STATE_DOWNLOADED); + do_check_eq(install.error, 0); + + do_check_neq(install.linkedInstalls, null); + do_check_eq(install.linkedInstalls.length, 1); + + let linked = install.linkedInstalls[0]; + do_print(linked.state); + do_check_eq(linked.error, ADDONS[filename]); + if (linked.error == 0) { + do_check_eq(linked.state, AddonManager.STATE_DOWNLOADED); + linked.cancel(); + } + else { + do_check_eq(linked.state, AddonManager.STATE_DOWNLOAD_FAILED); + } + + install.cancel(); +} + +for (let filename of Object.keys(ADDONS)) + add_task(test_addon.bind(null, filename)); diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini index 2106f5126a0..1d56a590c13 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini @@ -242,6 +242,7 @@ fail-if = buildapp == "mulet" || os == "android" [test_signed_install.js] run-sequentially = Uses hardcoded ports in xpi files. [test_signed_migrate.js] +[test_signed_multi.js] [test_startup.js] # Bug 676992: test consistently fails on Android fail-if = os == "android" diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini index df27e4da62c..65a8c23ec84 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini @@ -26,4 +26,5 @@ skip-if = appname != "firefox" [test_XPIcancel.js] [test_XPIStates.js] + [include:xpcshell-shared.ini] diff --git a/widget/GfxInfoBase.cpp b/widget/GfxInfoBase.cpp index b9d3022444e..3bbb10de5e8 100644 --- a/widget/GfxInfoBase.cpp +++ b/widget/GfxInfoBase.cpp @@ -151,6 +151,12 @@ GetPrefNameForFeature(int32_t aFeature) case nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION: name = BLACKLIST_PREF_BRANCH "webrtc.hw.acceleration"; break; + case nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION_ENCODE: + name = BLACKLIST_PREF_BRANCH "webrtc.hw.acceleration.encode"; + break; + case nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION_DECODE: + name = BLACKLIST_PREF_BRANCH "webrtc.hw.acceleration.decode"; + break; default: break; }; @@ -340,6 +346,10 @@ BlacklistFeatureToGfxFeature(const nsAString& aFeature) return nsIGfxInfo::FEATURE_WEBGL_MSAA; else if (aFeature.EqualsLiteral("STAGEFRIGHT")) return nsIGfxInfo::FEATURE_STAGEFRIGHT; + else if (aFeature.EqualsLiteral("WEBRTC_HW_ACCELERATION_ENCODE")) + return nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION_ENCODE; + else if (aFeature.EqualsLiteral("WEBRTC_HW_ACCELERATION_DECODE")) + return nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION_DECODE; else if (aFeature.EqualsLiteral("WEBRTC_HW_ACCELERATION")) return nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION; @@ -972,6 +982,8 @@ GfxInfoBase::EvaluateDownloadedBlacklist(nsTArray& aDriverInfo) nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_WEBGL_ANGLE, + nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION_ENCODE, + nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION_DECODE, nsIGfxInfo::FEATURE_WEBGL_MSAA, nsIGfxInfo::FEATURE_STAGEFRIGHT, nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION, diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index 5ffd9081612..e6368fb36da 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -1065,14 +1065,14 @@ PuppetWidget::GetNativeData(uint32_t aDataType) } return (void*)nativeData; } - case NS_NATIVE_WINDOW: + case NS_NATIVE_WIDGET: case NS_NATIVE_DISPLAY: + // These types are ignored (see bug 1183828). + break; + case NS_NATIVE_WINDOW: case NS_NATIVE_PLUGIN_PORT: case NS_NATIVE_GRAPHIC: case NS_NATIVE_SHELLWIDGET: - case NS_NATIVE_WIDGET: - NS_WARNING("nsWindow::GetNativeData not implemented for this type"); - break; default: NS_WARNING("nsWindow::GetNativeData called with bad value"); break; diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index b141b16b75d..807410e3a22 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -471,6 +471,27 @@ AndroidBridge::GetHandlersForMimeType(const nsAString& aMimeType, return true; } +bool +AndroidBridge::GetHWEncoderCapability() +{ + ALOG_BRIDGE("AndroidBridge::GetHWEncoderCapability"); + + bool value = GeckoAppShell::GetHWEncoderCapability(); + + return value; +} + + +bool +AndroidBridge::GetHWDecoderCapability() +{ + ALOG_BRIDGE("AndroidBridge::GetHWDecoderCapability"); + + bool value = GeckoAppShell::GetHWDecoderCapability(); + + return value; +} + bool AndroidBridge::GetHandlersForURL(const nsAString& aURL, nsIMutableArray* aHandlersArray, diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index ec89f075d3f..8d97b7fc02c 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -207,6 +207,9 @@ public: nsIHandlerApp **aDefaultApp = nullptr, const nsAString& aAction = EmptyString()); + bool GetHWEncoderCapability(); + bool GetHWDecoderCapability(); + void GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType); void GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt); diff --git a/widget/android/GeneratedJNIWrappers.cpp b/widget/android/GeneratedJNIWrappers.cpp index fddf93ef1dd..e8681c87135 100644 --- a/widget/android/GeneratedJNIWrappers.cpp +++ b/widget/android/GeneratedJNIWrappers.cpp @@ -278,6 +278,22 @@ mozilla::jni::String::LocalRef GeckoAppShell::GetExternalPublicDirectory(mozilla return mozilla::jni::Method::Call(nullptr, nullptr, a0); } +constexpr char GeckoAppShell::GetHWDecoderCapability_t::name[]; +constexpr char GeckoAppShell::GetHWDecoderCapability_t::signature[]; + +bool GeckoAppShell::GetHWDecoderCapability() +{ + return mozilla::jni::Method::Call(nullptr, nullptr); +} + +constexpr char GeckoAppShell::GetHWEncoderCapability_t::name[]; +constexpr char GeckoAppShell::GetHWEncoderCapability_t::signature[]; + +bool GeckoAppShell::GetHWEncoderCapability() +{ + return mozilla::jni::Method::Call(nullptr, nullptr); +} + constexpr char GeckoAppShell::GetHandlersForMimeTypeWrapper_t::name[]; constexpr char GeckoAppShell::GetHandlersForMimeTypeWrapper_t::signature[]; diff --git a/widget/android/GeneratedJNIWrappers.h b/widget/android/GeneratedJNIWrappers.h index ff2d6964e07..c0ee1a020ee 100644 --- a/widget/android/GeneratedJNIWrappers.h +++ b/widget/android/GeneratedJNIWrappers.h @@ -644,6 +644,40 @@ public: static mozilla::jni::String::LocalRef GetExternalPublicDirectory(mozilla::jni::String::Param); +public: + struct GetHWDecoderCapability_t { + typedef GeckoAppShell Owner; + typedef bool ReturnType; + typedef bool SetterType; + typedef mozilla::jni::Args<> Args; + static constexpr char name[] = "getHWDecoderCapability"; + static constexpr char signature[] = + "()Z"; + static const bool isStatic = true; + static const bool isMultithreaded = false; + static const mozilla::jni::ExceptionMode exceptionMode = + mozilla::jni::ExceptionMode::ABORT; + }; + + static bool GetHWDecoderCapability(); + +public: + struct GetHWEncoderCapability_t { + typedef GeckoAppShell Owner; + typedef bool ReturnType; + typedef bool SetterType; + typedef mozilla::jni::Args<> Args; + static constexpr char name[] = "getHWEncoderCapability"; + static constexpr char signature[] = + "()Z"; + static const bool isStatic = true; + static const bool isMultithreaded = false; + static const mozilla::jni::ExceptionMode exceptionMode = + mozilla::jni::ExceptionMode::ABORT; + }; + + static bool GetHWEncoderCapability(); + public: struct GetHandlersForMimeTypeWrapper_t { typedef GeckoAppShell Owner; diff --git a/widget/android/GfxInfo.cpp b/widget/android/GfxInfo.cpp index 5fdf1fa99b0..2555b08c1cb 100644 --- a/widget/android/GfxInfo.cpp +++ b/widget/android/GfxInfo.cpp @@ -587,20 +587,15 @@ GfxInfo::GetFeatureStatusImpl(int32_t aFeature, } } - if (aFeature == FEATURE_WEBRTC_HW_ACCELERATION) { - NS_LossyConvertUTF16toASCII cManufacturer(mManufacturer); - NS_LossyConvertUTF16toASCII cModel(mModel); - NS_LossyConvertUTF16toASCII cHardware(mHardware); - - if (cHardware.EqualsLiteral("hammerhead") && - CompareVersions(mOSVersion.get(), "4.4.2") >= 0 && - cManufacturer.Equals("lge", nsCaseInsensitiveCStringComparator()) && - cModel.Equals("nexus 5", nsCaseInsensitiveCStringComparator())) { - *aStatus = nsIGfxInfo::FEATURE_STATUS_OK; + if (aFeature == FEATURE_WEBRTC_HW_ACCELERATION_ENCODE) { + if (mozilla::AndroidBridge::Bridge()) { + *aStatus = mozilla::AndroidBridge::Bridge()->GetHWEncoderCapability() ? nsIGfxInfo::FEATURE_STATUS_OK : nsIGfxInfo::FEATURE_BLOCKED_DEVICE; return NS_OK; - } else { - // Blocklist all other devices except Nexus 5 which VP8 hardware acceleration is supported - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; + } + } + if (aFeature == FEATURE_WEBRTC_HW_ACCELERATION_DECODE) { + if (mozilla::AndroidBridge::Bridge()) { + *aStatus = mozilla::AndroidBridge::Bridge()->GetHWDecoderCapability() ? nsIGfxInfo::FEATURE_STATUS_OK : nsIGfxInfo::FEATURE_BLOCKED_DEVICE; return NS_OK; } } diff --git a/widget/gonk/HwcComposer2D.cpp b/widget/gonk/HwcComposer2D.cpp index 334adace3fe..d20a12d2f07 100644 --- a/widget/gonk/HwcComposer2D.cpp +++ b/widget/gonk/HwcComposer2D.cpp @@ -709,7 +709,7 @@ HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen) return false; } else if (blitComposite) { // BLIT Composition, flip DispSurface target - GetGonkDisplay()->UpdateDispSurface(aScreen->GetDpy(), aScreen->GetSur()); + GetGonkDisplay()->UpdateDispSurface(aScreen->GetEGLDisplay(), aScreen->GetEGLSurface()); DisplaySurface* dispSurface = aScreen->GetDisplaySurface(); if (!dispSurface) { LOGE("H/W Composition failed. NULL DispSurface."); @@ -731,7 +731,7 @@ HwcComposer2D::Render(nsIWidget* aWidget) // HWC module does not exist or mList is not created yet. if (!mHal->HasHwc() || !mList) { - return GetGonkDisplay()->SwapBuffers(screen->GetDpy(), screen->GetSur()); + return GetGonkDisplay()->SwapBuffers(screen->GetEGLDisplay(), screen->GetEGLSurface()); } else if (!mList && !ReallocLayerList()) { LOGE("Cannot realloc layer list"); return false; @@ -829,7 +829,7 @@ HwcComposer2D::Commit(nsScreenGonk* aScreen) bool HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen) { - mHal->SetEGLInfo(aScreen->GetDpy(), aScreen->GetSur()); + mHal->SetEGLInfo(aScreen->GetEGLDisplay(), aScreen->GetEGLSurface()); return !mHal->Set(mList, aScreen->GetDisplayType()); } @@ -837,7 +837,7 @@ bool HwcComposer2D::Render(nsIWidget* aWidget) { nsScreenGonk* screen = static_cast(aWidget)->GetScreen(); - GetGonkDisplay()->SwapBuffers(screen->GetDpy(), screen->GetSur()); + GetGonkDisplay()->SwapBuffers(screen->GetEGLDisplay(), screen->GetEGLSurface()); if (!mHal->HasHwc()) { return true; diff --git a/widget/gonk/HwcComposer2D.h b/widget/gonk/HwcComposer2D.h index a9d667b2db2..4da7cf85cf2 100644 --- a/widget/gonk/HwcComposer2D.h +++ b/widget/gonk/HwcComposer2D.h @@ -111,7 +111,7 @@ private: nsTArray mHwcLayerMap; bool mPrepared; bool mHasHWVsync; - nsRefPtr mCompositorParent; + layers::CompositorParent* mCompositorParent; Mutex mLock; }; diff --git a/widget/gonk/hwchal/HwcHALBase.h b/widget/gonk/hwchal/HwcHALBase.h index 8257c96f515..6a07ddd9157 100644 --- a/widget/gonk/hwchal/HwcHALBase.h +++ b/widget/gonk/hwchal/HwcHALBase.h @@ -89,8 +89,8 @@ public: virtual const hwc_rect_t GetHwcRect() const = 0; // Set EGL info (only ICS need this info) - virtual void SetEGLInfo(hwc_display_t aDpy, - hwc_surface_t aSur) = 0; + virtual void SetEGLInfo(hwc_display_t aEGLDisplay, + hwc_surface_t aEGLSurface) = 0; // HwcDevice query properties virtual bool Query(QueryType aType) = 0; diff --git a/widget/gonk/hwchal/HwcICS.cpp b/widget/gonk/hwchal/HwcICS.cpp index c37f94dbc61..92e953555de 100644 --- a/widget/gonk/hwchal/HwcICS.cpp +++ b/widget/gonk/hwchal/HwcICS.cpp @@ -34,16 +34,16 @@ HwcICS::HwcICS() HwcICS::~HwcICS() { mHwc = nullptr; - mDpy = nullptr; - mSur = nullptr; + mEGLDisplay = nullptr; + mEGLSurface = nullptr; } void -HwcICS::SetEGLInfo(hwc_display_t aDpy, - hwc_surface_t aSur) +HwcICS::SetEGLInfo(hwc_display_t aEGLDisplay, + hwc_surface_t aEGLSurface) { - mDpy = aDpy; - mSur = aSur; + mEGLDisplay = aEGLDisplay; + mEGLSurface = aEGLSurface; } bool @@ -74,7 +74,7 @@ HwcICS::Set(HwcList* aList, if (!mHwc) { return -1; } - return mHwc->set(mHwc, mDpy, mSur, aList); + return mHwc->set(mHwc, mEGLDisplay, mEGLSurface, aList); } int diff --git a/widget/gonk/hwchal/HwcICS.h b/widget/gonk/hwchal/HwcICS.h index 97d14995999..015b79a410d 100644 --- a/widget/gonk/hwchal/HwcICS.h +++ b/widget/gonk/hwchal/HwcICS.h @@ -33,8 +33,8 @@ public: virtual const hwc_rect_t GetHwcRect() const override { return {0}; } - virtual void SetEGLInfo(hwc_display_t aDpy, - hwc_surface_t aSur) override; + virtual void SetEGLInfo(hwc_display_t aEGLDisplay, + hwc_surface_t aEGLSurface) override; virtual bool Query(QueryType aType) override; @@ -61,8 +61,8 @@ public: private: HwcDevice *mHwc = nullptr; - hwc_display_t mDpy = nullptr; - hwc_surface_t mSur = nullptr; + hwc_display_t mEGLDisplay = nullptr; + hwc_surface_t mEGLSurface = nullptr; }; } // namespace mozilla diff --git a/widget/gonk/nsScreenManagerGonk.cpp b/widget/gonk/nsScreenManagerGonk.cpp index 8165d312764..607e7c72970 100644 --- a/widget/gonk/nsScreenManagerGonk.cpp +++ b/widget/gonk/nsScreenManagerGonk.cpp @@ -26,6 +26,7 @@ #include "HwcComposer2D.h" #include "VsyncSource.h" #include "nsWindow.h" +#include "mozilla/layers/CompositorParent.h" #include "mozilla/Services.h" #include "mozilla/ProcessPriorityManager.h" #include "nsIdleService.h" @@ -47,6 +48,7 @@ using namespace mozilla; using namespace mozilla::hal; using namespace mozilla::gfx; using namespace mozilla::gl; +using namespace mozilla::layers; using namespace mozilla::dom; namespace { @@ -120,8 +122,8 @@ nsScreenGonk::nsScreenGonk(uint32_t aId, , mDisplaySurface(aNativeData.mDisplaySurface) #endif , mDisplayType(aDisplayType) - , mDpy(EGL_NO_DISPLAY) - , mSur(EGL_NO_SURFACE) + , mEGLDisplay(EGL_NO_DISPLAY) + , mEGLSurface(EGL_NO_SURFACE) , mGLContext(nullptr) { if (mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &mVirtualBounds.width) || @@ -360,21 +362,24 @@ void nsScreenGonk::SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, gl::GLContext* aGLContext) { - mDpy = aDisplay; - mSur = aSurface; + MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + mEGLDisplay = aDisplay; + mEGLSurface = aSurface; mGLContext = aGLContext; } hwc_display_t -nsScreenGonk::GetDpy() +nsScreenGonk::GetEGLDisplay() { - return mDpy; + MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + return mEGLDisplay; } hwc_surface_t -nsScreenGonk::GetSur() +nsScreenGonk::GetEGLSurface() { - return mSur; + MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + return mEGLSurface; } NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager) diff --git a/widget/gonk/nsScreenManagerGonk.h b/widget/gonk/nsScreenManagerGonk.h index eccb9fb4a75..247c6874b47 100644 --- a/widget/gonk/nsScreenManagerGonk.h +++ b/widget/gonk/nsScreenManagerGonk.h @@ -90,8 +90,8 @@ public: // Set EGL info of primary display. Used for BLIT Composition. void SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, mozilla::gl::GLContext* aGLContext); - hwc_display_t GetDpy(); - hwc_surface_t GetSur(); + hwc_display_t GetEGLDisplay(); + hwc_surface_t GetEGLSurface(); protected: uint32_t mId; @@ -107,10 +107,12 @@ protected: #if ANDROID_VERSION >= 17 android::sp mDisplaySurface; #endif + + // Accessed and updated only on compositor thread GonkDisplay::DisplayType mDisplayType; - hwc_display_t mDpy; // Store for BLIT Composition and GonkDisplayICS - hwc_surface_t mSur; // Store for BLIT Composition and GonkDisplayICS - mozilla::gl::GLContext* mGLContext; // Store for BLIT Composition + hwc_display_t mEGLDisplay; + hwc_surface_t mEGLSurface; + mozilla::gl::GLContext* mGLContext; }; class nsScreenManagerGonk final : public nsIScreenManager diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index bc2c5c603dd..36b7ceff5bb 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -546,8 +546,13 @@ nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal) { switch (aDataType) { case NS_NATIVE_OPENGL_CONTEXT: - // Called after primary display's GLContextEGL creation. GLContext* context = reinterpret_cast(aVal); + if (!context) { + mScreen->SetEGLInfo(EGL_NO_DISPLAY, + EGL_NO_SURFACE, + nullptr); + return; + } mScreen->SetEGLInfo(GLContextEGL::Cast(context)->GetEGLDisplay(), GLContextEGL::Cast(context)->GetEGLSurface(), context); @@ -758,6 +763,16 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, return mLayerManager; } +void +nsWindow::DestroyCompositor() +{ + if (mCompositorParent && mScreen->IsPrimaryScreen()) { + // Unset CompositorParent + mComposer2D->SetCompositorParent(nullptr); + } + nsBaseWidget::DestroyCompositor(); +} + void nsWindow::BringToTop() { diff --git a/widget/gonk/nsWindow.h b/widget/gonk/nsWindow.h index 7f6d527d1d6..ab3a3cc3fed 100644 --- a/widget/gonk/nsWindow.h +++ b/widget/gonk/nsWindow.h @@ -113,6 +113,7 @@ public: LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT, bool* aAllowRetaining = nullptr); + virtual void DestroyCompositor(); NS_IMETHOD_(void) SetInputContext(const InputContext& aContext, const InputContextAction& aAction); diff --git a/widget/gtk/nsGtkIMModule.cpp b/widget/gtk/IMContextWrapper.cpp similarity index 70% rename from widget/gtk/nsGtkIMModule.cpp rename to widget/gtk/IMContextWrapper.cpp index ae4a20c3c39..e58917407ee 100644 --- a/widget/gtk/nsGtkIMModule.cpp +++ b/widget/gtk/IMContextWrapper.cpp @@ -7,7 +7,7 @@ #include "mozilla/Logging.h" #include "prtime.h" -#include "nsGtkIMModule.h" +#include "IMContextWrapper.h" #include "nsWindow.h" #include "mozilla/AutoRestore.h" #include "mozilla/Likely.h" @@ -16,15 +16,15 @@ #include "mozilla/TextEvents.h" #include "WritingModes.h" -using namespace mozilla; -using namespace mozilla::widget; +namespace mozilla { +namespace widget { PRLogModuleInfo* gGtkIMLog = nullptr; -static const char* -GetBoolName(bool aBool) +static inline const char* +ToChar(bool aBool) { - return aBool ? "true" : "false"; + return aBool ? "true" : "false"; } static const char* @@ -97,13 +97,13 @@ public: const static bool kUseSimpleContextDefault = MOZ_WIDGET_GTK == 2; /****************************************************************************** - * nsGtkIMModule + * IMContextWrapper ******************************************************************************/ -nsGtkIMModule* nsGtkIMModule::sLastFocusedModule = nullptr; -bool nsGtkIMModule::sUseSimpleContext; +IMContextWrapper* IMContextWrapper::sLastFocusedContext = nullptr; +bool IMContextWrapper::sUseSimpleContext; -nsGtkIMModule::nsGtkIMModule(nsWindow* aOwnerWindow) +IMContextWrapper::IMContextWrapper(nsWindow* aOwnerWindow) : mOwnerWindow(aOwnerWindow) , mLastFocusedWindow(nullptr) , mContext(nullptr) @@ -133,10 +133,10 @@ nsGtkIMModule::nsGtkIMModule(nsWindow* aOwnerWindow) } void -nsGtkIMModule::Init() +IMContextWrapper::Init() { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): Init, mOwnerWindow=%p", + ("GTKIM: %p Init(), mOwnerWindow=%p", this, mOwnerWindow)); MozContainer* container = mOwnerWindow->GetMozContainer(); @@ -150,45 +150,39 @@ nsGtkIMModule::Init() mContext = gtk_im_multicontext_new(); gtk_im_context_set_client_window(mContext, gdkWindow); g_signal_connect(mContext, "preedit_changed", - G_CALLBACK(nsGtkIMModule::OnChangeCompositionCallback), - this); + G_CALLBACK(IMContextWrapper::OnChangeCompositionCallback), this); g_signal_connect(mContext, "retrieve_surrounding", - G_CALLBACK(nsGtkIMModule::OnRetrieveSurroundingCallback), - this); + G_CALLBACK(IMContextWrapper::OnRetrieveSurroundingCallback), this); g_signal_connect(mContext, "delete_surrounding", - G_CALLBACK(nsGtkIMModule::OnDeleteSurroundingCallback), - this); + G_CALLBACK(IMContextWrapper::OnDeleteSurroundingCallback), this); g_signal_connect(mContext, "commit", - G_CALLBACK(nsGtkIMModule::OnCommitCompositionCallback), - this); + G_CALLBACK(IMContextWrapper::OnCommitCompositionCallback), this); g_signal_connect(mContext, "preedit_start", - G_CALLBACK(nsGtkIMModule::OnStartCompositionCallback), - this); + G_CALLBACK(IMContextWrapper::OnStartCompositionCallback), this); g_signal_connect(mContext, "preedit_end", - G_CALLBACK(nsGtkIMModule::OnEndCompositionCallback), - this); + G_CALLBACK(IMContextWrapper::OnEndCompositionCallback), this); // Simple context if (sUseSimpleContext) { mSimpleContext = gtk_im_context_simple_new(); gtk_im_context_set_client_window(mSimpleContext, gdkWindow); g_signal_connect(mSimpleContext, "preedit_changed", - G_CALLBACK(&nsGtkIMModule::OnChangeCompositionCallback), + G_CALLBACK(&IMContextWrapper::OnChangeCompositionCallback), this); g_signal_connect(mSimpleContext, "retrieve_surrounding", - G_CALLBACK(&nsGtkIMModule::OnRetrieveSurroundingCallback), + G_CALLBACK(&IMContextWrapper::OnRetrieveSurroundingCallback), this); g_signal_connect(mSimpleContext, "delete_surrounding", - G_CALLBACK(&nsGtkIMModule::OnDeleteSurroundingCallback), + G_CALLBACK(&IMContextWrapper::OnDeleteSurroundingCallback), this); g_signal_connect(mSimpleContext, "commit", - G_CALLBACK(&nsGtkIMModule::OnCommitCompositionCallback), + G_CALLBACK(&IMContextWrapper::OnCommitCompositionCallback), this); g_signal_connect(mSimpleContext, "preedit_start", - G_CALLBACK(nsGtkIMModule::OnStartCompositionCallback), + G_CALLBACK(IMContextWrapper::OnStartCompositionCallback), this); g_signal_connect(mSimpleContext, "preedit_end", - G_CALLBACK(nsGtkIMModule::OnEndCompositionCallback), + G_CALLBACK(IMContextWrapper::OnEndCompositionCallback), this); } @@ -197,21 +191,22 @@ nsGtkIMModule::Init() gtk_im_context_set_client_window(mDummyContext, gdkWindow); } -nsGtkIMModule::~nsGtkIMModule() +IMContextWrapper::~IMContextWrapper() { - if (this == sLastFocusedModule) { - sLastFocusedModule = nullptr; + if (this == sLastFocusedContext) { + sLastFocusedContext = nullptr; } MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p) was gone", this)); + ("GTKIM: %p ~IMContextWrapper()", this)); } void -nsGtkIMModule::OnDestroyWindow(nsWindow* aWindow) +IMContextWrapper::OnDestroyWindow(nsWindow* aWindow) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnDestroyWindow, aWindow=%p, mLastFocusedWindow=%p, mOwnerWindow=%p, mLastFocusedModule=%p", - this, aWindow, mLastFocusedWindow, mOwnerWindow, sLastFocusedModule)); + ("GTKIM: %p OnDestroyWindow(aWindow=%p), mLastFocusedWindow=%p, " + "mOwnerWindow=%p, mLastFocusedModule=%p", + this, aWindow, mLastFocusedWindow, mOwnerWindow, sLastFocusedContext)); NS_PRECONDITION(aWindow, "aWindow must not be null"); @@ -227,8 +222,8 @@ nsGtkIMModule::OnDestroyWindow(nsWindow* aWindow) return; } - if (sLastFocusedModule == this) { - sLastFocusedModule = nullptr; + if (sLastFocusedContext == this) { + sLastFocusedContext = nullptr; } /** @@ -269,8 +264,9 @@ nsGtkIMModule::OnDestroyWindow(nsWindow* aWindow) mLastFocusedWindow = nullptr; mInputContext.mIMEState.mEnabled = IMEState::DISABLED; - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" SUCCEEDED, Completely destroyed")); + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p OnDestroyWindow(), succeeded, Completely destroyed", + this)); } // Work around gtk bug http://bugzilla.gnome.org/show_bug.cgi?id=483223: @@ -292,7 +288,7 @@ nsGtkIMModule::OnDestroyWindow(nsWindow* aWindow) // handlers (where possible). void -nsGtkIMModule::PrepareToDestroyContext(GtkIMContext *aContext) +IMContextWrapper::PrepareToDestroyContext(GtkIMContext* aContext) { #if (MOZ_WIDGET_GTK == 2) GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT(aContext); @@ -316,30 +312,30 @@ nsGtkIMModule::PrepareToDestroyContext(GtkIMContext *aContext) } void -nsGtkIMModule::OnFocusWindow(nsWindow* aWindow) +IMContextWrapper::OnFocusWindow(nsWindow* aWindow) { if (MOZ_UNLIKELY(IsDestroyed())) { return; } MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnFocusWindow, aWindow=%p, mLastFocusedWindow=%p", + ("GTKIM: %p OnFocusWindow(aWindow=%p), mLastFocusedWindow=%p", this, aWindow, mLastFocusedWindow)); mLastFocusedWindow = aWindow; Focus(); } void -nsGtkIMModule::OnBlurWindow(nsWindow* aWindow) +IMContextWrapper::OnBlurWindow(nsWindow* aWindow) { if (MOZ_UNLIKELY(IsDestroyed())) { return; } MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnBlurWindow, aWindow=%p, mLastFocusedWindow=%p, " + ("GTKIM: %p OnBlurWindow(aWindow=%p), mLastFocusedWindow=%p, " "mIsIMFocused=%s", - this, aWindow, mLastFocusedWindow, GetBoolName(mIsIMFocused))); + this, aWindow, mLastFocusedWindow, ToChar(mIsIMFocused))); if (!mIsIMFocused || mLastFocusedWindow != aWindow) { return; @@ -349,8 +345,9 @@ nsGtkIMModule::OnBlurWindow(nsWindow* aWindow) } bool -nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent, - bool aKeyDownEventWasSent /* = false */) +IMContextWrapper::OnKeyEvent(nsWindow* aCaller, + GdkEventKey* aEvent, + bool aKeyDownEventWasSent /* = false */) { NS_PRECONDITION(aEvent, "aEvent must be non-null"); @@ -360,18 +357,19 @@ nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent, } MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnKeyEvent, aCaller=%p, aKeyDownEventWasSent=%s, " + ("GTKIM: %p OnKeyEvent(aCaller=%p, aKeyDownEventWasSent=%s), " "mCompositionState=%s, current context=%p, active context=%p, " "aEvent(%p): { type=%s, keyval=%s, unicode=0x%X }", - this, aCaller, GetBoolName(aKeyDownEventWasSent), + this, aCaller, ToChar(aKeyDownEventWasSent), GetCompositionStateName(), GetCurrentContext(), GetActiveContext(), aEvent, GetEventType(aEvent), gdk_keyval_name(aEvent->keyval), gdk_keyval_to_unicode(aEvent->keyval))); if (aCaller != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, the caller isn't focused window, mLastFocusedWindow=%p", - mLastFocusedWindow)); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnKeyEvent(), FAILED, the caller isn't focused " + "window, mLastFocusedWindow=%p", + this, mLastFocusedWindow)); return false; } @@ -379,8 +377,9 @@ nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent, // current context since the user expects so. GtkIMContext* currentContext = GetCurrentContext(); if (MOZ_UNLIKELY(!currentContext)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no context")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnKeyEvent(), FAILED, there are no context", + this)); return false; } @@ -427,23 +426,23 @@ nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent, } } - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" filterThisEvent=%s (isFiltered=%s, mFilterKeyEvent=%s), " - "mCompositionState=%s", - GetBoolName(filterThisEvent), GetBoolName(isFiltered), - GetBoolName(mFilterKeyEvent), GetCompositionStateName())); + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p OnKeyEvent(), succeeded, filterThisEvent=%s " + "(isFiltered=%s, mFilterKeyEvent=%s), mCompositionState=%s", + this, ToChar(filterThisEvent), ToChar(isFiltered), + ToChar(mFilterKeyEvent), GetCompositionStateName())); return filterThisEvent; } void -nsGtkIMModule::OnFocusChangeInGecko(bool aFocus) +IMContextWrapper::OnFocusChangeInGecko(bool aFocus) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnFocusChangeInGecko, aFocus=%s, " + ("GTKIM: %p OnFocusChangeInGecko(aFocus=%s), " "mCompositionState=%s, mIsIMFocused=%s", - this, GetBoolName(aFocus), GetCompositionStateName(), - GetBoolName(mIsIMFocused))); + this, ToChar(aFocus), GetCompositionStateName(), + ToChar(mIsIMFocused))); // We shouldn't carry over the removed string to another editor. mSelectedString.Truncate(); @@ -451,20 +450,21 @@ nsGtkIMModule::OnFocusChangeInGecko(bool aFocus) } void -nsGtkIMModule::ResetIME() +IMContextWrapper::ResetIME() { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): ResetIME, mCompositionState=%s, mIsIMFocused=%s", - this, GetCompositionStateName(), GetBoolName(mIsIMFocused))); + ("GTKIM: %p ResetIME(), mCompositionState=%s, mIsIMFocused=%s", + this, GetCompositionStateName(), ToChar(mIsIMFocused))); GtkIMContext* activeContext = GetActiveContext(); if (MOZ_UNLIKELY(!activeContext)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no context")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p ResetIME(), FAILED, there are no context", + this)); return; } - nsRefPtr kungFuDeathGrip(this); + nsRefPtr kungFuDeathGrip(this); nsRefPtr lastFocusedWindow(mLastFocusedWindow); gtk_im_context_reset(activeContext); @@ -480,13 +480,13 @@ nsGtkIMModule::ResetIME() nsAutoString compositionString; GetCompositionString(activeContext, compositionString); - MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): ResetIME() called gtk_im_context_reset(), " + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p ResetIME() called gtk_im_context_reset(), " "activeContext=%p, mCompositionState=%s, compositionString=%s, " "mIsIMFocused=%s", this, activeContext, GetCompositionStateName(), NS_ConvertUTF16toUTF8(compositionString).get(), - GetBoolName(mIsIMFocused))); + ToChar(mIsIMFocused))); // XXX IIIMF (ATOK X3 which is one of the Language Engine of it is still // used in Japan!) sends only "preedit_changed" signal with empty @@ -500,21 +500,22 @@ nsGtkIMModule::ResetIME() } nsresult -nsGtkIMModule::EndIMEComposition(nsWindow* aCaller) +IMContextWrapper::EndIMEComposition(nsWindow* aCaller) { if (MOZ_UNLIKELY(IsDestroyed())) { return NS_OK; } MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): EndIMEComposition, aCaller=%p, " + ("GTKIM: %p EndIMEComposition(aCaller=%p), " "mCompositionState=%s", this, aCaller, GetCompositionStateName())); if (aCaller != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" WARNING: the caller isn't focused window, mLastFocusedWindow=%p", - mLastFocusedWindow)); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p EndIMEComposition(), FAILED, the caller isn't " + "focused window, mLastFocusedWindow=%p", + this, mLastFocusedWindow)); return NS_OK; } @@ -536,7 +537,7 @@ nsGtkIMModule::EndIMEComposition(nsWindow* aCaller) } void -nsGtkIMModule::OnLayoutChange() +IMContextWrapper::OnLayoutChange() { if (MOZ_UNLIKELY(IsDestroyed())) { return; @@ -553,7 +554,7 @@ nsGtkIMModule::OnLayoutChange() } void -nsGtkIMModule::OnUpdateComposition() +IMContextWrapper::OnUpdateComposition() { if (MOZ_UNLIKELY(IsDestroyed())) { return; @@ -575,37 +576,43 @@ nsGtkIMModule::OnUpdateComposition() } void -nsGtkIMModule::SetInputContext(nsWindow* aCaller, - const InputContext* aContext, - const InputContextAction* aAction) +IMContextWrapper::SetInputContext(nsWindow* aCaller, + const InputContext* aContext, + const InputContextAction* aAction) { if (MOZ_UNLIKELY(IsDestroyed())) { return; } MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): SetInputContext, aCaller=%p, aState=%s mHTMLInputType=%s", + ("GTKIM: %p SetInputContext(aCaller=%p, aContext={ mIMEState={ " + "mEnabled=%s }, mHTMLInputType=%s })", this, aCaller, GetEnabledStateName(aContext->mIMEState.mEnabled), NS_ConvertUTF16toUTF8(aContext->mHTMLInputType).get())); if (aCaller != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, the caller isn't focused window, mLastFocusedWindow=%p", - mLastFocusedWindow)); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p SetInputContext(), FAILED, " + "the caller isn't focused window, mLastFocusedWindow=%p", + this, mLastFocusedWindow)); return; } if (!mContext) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no context")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p SetInputContext(), FAILED, " + "there are no context", + this)); return; } - if (sLastFocusedModule != this) { + if (sLastFocusedContext != this) { mInputContext = *aContext; - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" SUCCEEDED, but we're not active")); + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p SetInputContext(), succeeded, " + "but we're not active", + this)); return; } @@ -676,14 +683,14 @@ nsGtkIMModule::SetInputContext(nsWindow* aCaller, } InputContext -nsGtkIMModule::GetInputContext() +IMContextWrapper::GetInputContext() { mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED; return mInputContext; } GtkIMContext* -nsGtkIMModule::GetCurrentContext() const +IMContextWrapper::GetCurrentContext() const { if (IsEnabled()) { return mContext; @@ -695,7 +702,7 @@ nsGtkIMModule::GetCurrentContext() const } bool -nsGtkIMModule::IsValidContext(GtkIMContext* aContext) const +IMContextWrapper::IsValidContext(GtkIMContext* aContext) const { if (!aContext) { return false; @@ -706,7 +713,7 @@ nsGtkIMModule::IsValidContext(GtkIMContext* aContext) const } bool -nsGtkIMModule::IsEnabled() const +IMContextWrapper::IsEnabled() const { return mInputContext.mIMEState.mEnabled == IMEState::ENABLED || mInputContext.mIMEState.mEnabled == IMEState::PLUGIN || @@ -715,30 +722,31 @@ nsGtkIMModule::IsEnabled() const } void -nsGtkIMModule::Focus() +IMContextWrapper::Focus() { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): Focus, sLastFocusedModule=%p", - this, sLastFocusedModule)); + ("GTKIM: %p Focus(), sLastFocusedContext=%p", + this, sLastFocusedContext)); if (mIsIMFocused) { - NS_ASSERTION(sLastFocusedModule == this, + NS_ASSERTION(sLastFocusedContext == this, "We're not active, but the IM was focused?"); return; } GtkIMContext* currentContext = GetCurrentContext(); if (!currentContext) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no context")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p Focus(), FAILED, there are no context", + this)); return; } - if (sLastFocusedModule && sLastFocusedModule != this) { - sLastFocusedModule->Blur(); + if (sLastFocusedContext && sLastFocusedContext != this) { + sLastFocusedContext->Blur(); } - sLastFocusedModule = this; + sLastFocusedContext = this; gtk_im_context_focus_in(currentContext); mIsIMFocused = true; @@ -752,11 +760,11 @@ nsGtkIMModule::Focus() } void -nsGtkIMModule::Blur() +IMContextWrapper::Blur() { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): Blur, mIsIMFocused=%s", - this, GetBoolName(mIsIMFocused))); + ("GTKIM: %p Blur(), mIsIMFocused=%s", + this, ToChar(mIsIMFocused))); if (!mIsIMFocused) { return; @@ -764,8 +772,9 @@ nsGtkIMModule::Blur() GtkIMContext* currentContext = GetCurrentContext(); if (!currentContext) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no context")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p Blur(), FAILED, there are no context", + this)); return; } @@ -774,8 +783,8 @@ nsGtkIMModule::Blur() } void -nsGtkIMModule::OnSelectionChange(nsWindow* aCaller, - const IMENotification& aIMENotification) +IMContextWrapper::OnSelectionChange(nsWindow* aCaller, + const IMENotification& aIMENotification) { mSelection.Assign(aIMENotification); @@ -787,23 +796,23 @@ nsGtkIMModule::OnSelectionChange(nsWindow* aCaller, aIMENotification.mSelectionChangeData; MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnSelectionChange(aCaller=0x%p, aIMENotification={ " + ("GTKIM: %p OnSelectionChange(aCaller=0x%p, aIMENotification={ " "mSelectionChangeData={ mOffset=%u, Length()=%u, mReversed=%s, " "mWritingMode=%s, mCausedByComposition=%s, mCausedBySelectionEvent=%s " "} }), mCompositionState=%s, mIsDeletingSurrounding=%s", this, aCaller, selectionChangeData.mOffset, selectionChangeData.Length(), - GetBoolName(selectionChangeData.mReversed), + ToChar(selectionChangeData.mReversed), GetWritingModeName(selectionChangeData.GetWritingMode()).get(), - GetBoolName(selectionChangeData.mCausedByComposition), - GetBoolName(selectionChangeData.mCausedBySelectionEvent), - GetCompositionStateName(), GetBoolName(mIsDeletingSurrounding))); + ToChar(selectionChangeData.mCausedByComposition), + ToChar(selectionChangeData.mCausedBySelectionEvent), + GetCompositionStateName(), ToChar(mIsDeletingSurrounding))); if (aCaller != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" WARNING: the caller isn't focused window, " - "mLastFocusedWindow=%p", - mLastFocusedWindow)); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnSelectionChange(), FAILED, " + "the caller isn't focused window, mLastFocusedWindow=%p", + this, mLastFocusedWindow)); return; } @@ -819,16 +828,19 @@ nsGtkIMModule::OnSelectionChange(nsWindow* aCaller, // we should ignore selection change notification. if (mCompositionState == eCompositionState_CompositionStartDispatched) { if (NS_WARN_IF(!mSelection.IsValid())) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" ERROR: new offset is too large, cannot keep composing")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnSelectionChange(), FAILED, " + "new offset is too large, cannot keep composing", + this)); } else { // Modify the selection start offset with new offset. mCompositionStart = mSelection.mOffset; // XXX We should modify mSelectedString? But how? - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" NOTE: mCompositionStart is updated to %u, " - "the selection change doesn't cause resetting IM context", - mCompositionStart)); + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p OnSelectionChange(), ignored, mCompositionStart " + "is updated to %u, the selection change doesn't cause " + "resetting IM context", + this, mCompositionStart)); // And don't reset the IM context. return; } @@ -852,24 +864,26 @@ nsGtkIMModule::OnSelectionChange(nsWindow* aCaller, /* static */ void -nsGtkIMModule::OnStartCompositionCallback(GtkIMContext *aContext, - nsGtkIMModule* aModule) +IMContextWrapper::OnStartCompositionCallback(GtkIMContext* aContext, + IMContextWrapper* aModule) { aModule->OnStartCompositionNative(aContext); } void -nsGtkIMModule::OnStartCompositionNative(GtkIMContext *aContext) +IMContextWrapper::OnStartCompositionNative(GtkIMContext* aContext) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnStartCompositionNative, aContext=%p, " + ("GTKIM: %p OnStartCompositionNative(aContext=%p), " "current context=%p", this, aContext, GetCurrentContext())); // See bug 472635, we should do nothing if IM context doesn't match. if (GetCurrentContext() != aContext) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, given context doesn't match")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnStartCompositionNative(), FAILED, " + "given context doesn't match", + this)); return; } @@ -884,25 +898,27 @@ nsGtkIMModule::OnStartCompositionNative(GtkIMContext *aContext) /* static */ void -nsGtkIMModule::OnEndCompositionCallback(GtkIMContext *aContext, - nsGtkIMModule* aModule) +IMContextWrapper::OnEndCompositionCallback(GtkIMContext* aContext, + IMContextWrapper* aModule) { aModule->OnEndCompositionNative(aContext); } void -nsGtkIMModule::OnEndCompositionNative(GtkIMContext *aContext) +IMContextWrapper::OnEndCompositionNative(GtkIMContext* aContext) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnEndCompositionNative, aContext=%p", + ("GTKIM: %p OnEndCompositionNative(aContext=%p)", this, aContext)); // See bug 472635, we should do nothing if IM context doesn't match. // Note that if this is called after focus move, the context may different // from any our owning context. if (!IsValidContext(aContext)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, given context doesn't match with any context")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnEndCompositionNative(), FAILED, " + "given context doesn't match with any context", + this)); return; } @@ -920,25 +936,27 @@ nsGtkIMModule::OnEndCompositionNative(GtkIMContext *aContext) /* static */ void -nsGtkIMModule::OnChangeCompositionCallback(GtkIMContext *aContext, - nsGtkIMModule* aModule) +IMContextWrapper::OnChangeCompositionCallback(GtkIMContext* aContext, + IMContextWrapper* aModule) { aModule->OnChangeCompositionNative(aContext); } void -nsGtkIMModule::OnChangeCompositionNative(GtkIMContext *aContext) +IMContextWrapper::OnChangeCompositionNative(GtkIMContext* aContext) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnChangeCompositionNative, aContext=%p", + ("GTKIM: %p OnChangeCompositionNative(aContext=%p)", this, aContext)); // See bug 472635, we should do nothing if IM context doesn't match. // Note that if this is called after focus move, the context may different // from any our owning context. if (!IsValidContext(aContext)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, given context doesn't match with any context")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnChangeCompositionNative(), FAILED, " + "given context doesn't match with any context", + this)); return; } @@ -955,24 +973,26 @@ nsGtkIMModule::OnChangeCompositionNative(GtkIMContext *aContext) /* static */ gboolean -nsGtkIMModule::OnRetrieveSurroundingCallback(GtkIMContext *aContext, - nsGtkIMModule *aModule) +IMContextWrapper::OnRetrieveSurroundingCallback(GtkIMContext* aContext, + IMContextWrapper* aModule) { return aModule->OnRetrieveSurroundingNative(aContext); } gboolean -nsGtkIMModule::OnRetrieveSurroundingNative(GtkIMContext *aContext) +IMContextWrapper::OnRetrieveSurroundingNative(GtkIMContext* aContext) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnRetrieveSurroundingNative, aContext=%p, " + ("GTKIM: %p OnRetrieveSurroundingNative(aContext=%p), " "current context=%p", this, aContext, GetCurrentContext())); // See bug 472635, we should do nothing if IM context doesn't match. if (GetCurrentContext() != aContext) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, given context doesn't match")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnRetrieveSurroundingNative(), FAILED, " + "given context doesn't match", + this)); return FALSE; } @@ -992,28 +1012,30 @@ nsGtkIMModule::OnRetrieveSurroundingNative(GtkIMContext *aContext) /* static */ gboolean -nsGtkIMModule::OnDeleteSurroundingCallback(GtkIMContext *aContext, - gint aOffset, - gint aNChars, - nsGtkIMModule *aModule) +IMContextWrapper::OnDeleteSurroundingCallback(GtkIMContext* aContext, + gint aOffset, + gint aNChars, + IMContextWrapper* aModule) { return aModule->OnDeleteSurroundingNative(aContext, aOffset, aNChars); } gboolean -nsGtkIMModule::OnDeleteSurroundingNative(GtkIMContext *aContext, - gint aOffset, - gint aNChars) +IMContextWrapper::OnDeleteSurroundingNative(GtkIMContext* aContext, + gint aOffset, + gint aNChars) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnDeleteSurroundingNative, aContext=%p, " - "current context=%p", + ("GTKIM: %p OnDeleteSurroundingNative(aContext=%p, aOffset=%ld, " + "aNChar=%ld), current context=%p", this, aContext, GetCurrentContext())); // See bug 472635, we should do nothing if IM context doesn't match. if (GetCurrentContext() != aContext) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, given context doesn't match")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnDeleteSurroundingNative(), FAILED, " + "given context doesn't match", + this)); return FALSE; } @@ -1024,38 +1046,42 @@ nsGtkIMModule::OnDeleteSurroundingNative(GtkIMContext *aContext, } // failed - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, cannot delete text")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnDeleteSurroundingNative(), FAILED, " + "cannot delete text", + this)); return FALSE; } /* static */ void -nsGtkIMModule::OnCommitCompositionCallback(GtkIMContext *aContext, - const gchar *aString, - nsGtkIMModule* aModule) +IMContextWrapper::OnCommitCompositionCallback(GtkIMContext* aContext, + const gchar* aString, + IMContextWrapper* aModule) { aModule->OnCommitCompositionNative(aContext, aString); } void -nsGtkIMModule::OnCommitCompositionNative(GtkIMContext *aContext, - const gchar *aUTF8Char) +IMContextWrapper::OnCommitCompositionNative(GtkIMContext* aContext, + const gchar* aUTF8Char) { const gchar emptyStr = 0; const gchar *commitString = aUTF8Char ? aUTF8Char : &emptyStr; MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnCommitCompositionNative, aContext=%p, " + ("GTKIM: %p OnCommitCompositionNative(aContext=%p), " "current context=%p, active context=%p, commitString=\"%s\", " "mProcessingKeyEvent=%p, IsComposingOn(aContext)=%s", this, aContext, GetCurrentContext(), GetActiveContext(), commitString, - mProcessingKeyEvent, GetBoolName(IsComposingOn(aContext)))); + mProcessingKeyEvent, ToChar(IsComposingOn(aContext)))); // See bug 472635, we should do nothing if IM context doesn't match. if (!IsValidContext(aContext)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, given context doesn't match")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p OnCommitCompositionNative(), FAILED, " + "given context doesn't match", + this)); return; } @@ -1085,7 +1111,8 @@ nsGtkIMModule::OnCommitCompositionNative(GtkIMContext *aContext, if (!strcmp(commitString, keyval_utf8)) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): OnCommitCompositionNative, we'll send normal key event", + ("GTKIM: %p OnCommitCompositionNative(), " + "we'll send normal key event", this)); mFilterKeyEvent = false; return; @@ -1098,8 +1125,8 @@ nsGtkIMModule::OnCommitCompositionNative(GtkIMContext *aContext, } void -nsGtkIMModule::GetCompositionString(GtkIMContext* aContext, - nsAString& aCompositionString) +IMContextWrapper::GetCompositionString(GtkIMContext* aContext, + nsAString& aCompositionString) { gchar *preedit_string; gint cursor_pos; @@ -1113,35 +1140,42 @@ nsGtkIMModule::GetCompositionString(GtkIMContext* aContext, } MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): GetCompositionString, result=\"%s\"", - this, preedit_string)); + ("GTKIM: %p GetCompositionString(aContext=%p), " + "aCompositionString=\"%s\"", + this, aContext, preedit_string)); pango_attr_list_unref(feedback_list); g_free(preedit_string); } bool -nsGtkIMModule::DispatchCompositionStart(GtkIMContext* aContext) +IMContextWrapper::DispatchCompositionStart(GtkIMContext* aContext) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): DispatchCompositionStart, aContext=%p", + ("GTKIM: %p DispatchCompositionStart(aContext=%p)", this, aContext)); if (IsComposing()) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" WARNING, we're already in composition")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionStart(), FAILED, " + "we're already in composition", + this)); return true; } if (!mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no focused window in this module")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionStart(), FAILED, " + "there are no focused window in this module", + this)); return false; } if (NS_WARN_IF(!EnsureToCacheSelection())) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, cannot query the selection offset")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionStart(), FAILED, " + "cannot query the selection offset", + this)); return false; } @@ -1160,18 +1194,23 @@ nsGtkIMModule::DispatchCompositionStart(GtkIMContext* aContext) bool isCancelled; mLastFocusedWindow->DispatchKeyDownEvent(mProcessingKeyEvent, &isCancelled); - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" keydown event is dispatched")); + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p DispatchCompositionStart(), FAILED, keydown event " + "is dispatched", + this)); if (static_cast(kungFuDeathGrip.get())->IsDestroyed() || kungFuDeathGrip != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" NOTE, the focused widget was destroyed/changed by keydown event")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionStart(), FAILED, the focused " + "widget was destroyed/changed by keydown event", + this)); return false; } } - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" mCompositionStart=%u", mCompositionStart)); + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p DispatchCompositionStart(), FAILED, mCompositionStart=%u", + this, mCompositionStart)); mCompositionState = eCompositionState_CompositionStartDispatched; WidgetCompositionEvent compEvent(true, NS_COMPOSITION_START, mLastFocusedWindow); @@ -1181,8 +1220,10 @@ nsGtkIMModule::DispatchCompositionStart(GtkIMContext* aContext) mLastFocusedWindow->DispatchEvent(&compEvent, status); if (static_cast(kungFuDeathGrip.get())->IsDestroyed() || kungFuDeathGrip != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" NOTE, the focused widget was destroyed/changed by compositionstart event")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionStart(), FAILED, the focused " + "widget was destroyed/changed by compositionstart event", + this)); return false; } @@ -1190,23 +1231,27 @@ nsGtkIMModule::DispatchCompositionStart(GtkIMContext* aContext) } bool -nsGtkIMModule::DispatchCompositionChangeEvent( - GtkIMContext* aContext, - const nsAString& aCompositionString) +IMContextWrapper::DispatchCompositionChangeEvent( + GtkIMContext* aContext, + const nsAString& aCompositionString) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): DispatchCompositionChangeEvent, aContext=%p", + ("GTKIM: %p DispatchCompositionChangeEvent(aContext=%p)", this, aContext)); if (!mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no focused window in this module")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionChangeEvent(), FAILED, " + "there are no focused window in this module", + this)); return false; } if (!IsComposing()) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" The composition wasn't started, force starting...")); + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p DispatchCompositionChangeEvent(), the composition " + "wasn't started, force starting...", + this)); nsCOMPtr kungFuDeathGrip = mLastFocusedWindow; if (!DispatchCompositionStart(aContext)) { return false; @@ -1254,40 +1299,47 @@ nsGtkIMModule::DispatchCompositionChangeEvent( mLastFocusedWindow->DispatchEvent(&compositionChangeEvent, status); if (lastFocusedWindow->IsDestroyed() || lastFocusedWindow != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" NOTE, the focused widget was destroyed/changed by " - "compositionchange event")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionChangeEvent(), FAILED, the " + "focused widget was destroyed/changed by " + "compositionchange event", + this)); return false; } return true; } bool -nsGtkIMModule::DispatchCompositionCommitEvent( - GtkIMContext* aContext, - const nsAString* aCommitString) +IMContextWrapper::DispatchCompositionCommitEvent( + GtkIMContext* aContext, + const nsAString* aCommitString) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): DispatchCompositionCommitEvent, aContext=%p, " - "aCommitString=%p, (\"%s\")", + ("GTKIM: %p DispatchCompositionCommitEvent(aContext=%p, " + "aCommitString=%p, (\"%s\"))", this, aContext, aCommitString, aCommitString ? NS_ConvertUTF16toUTF8(*aCommitString).get() : "")); if (!mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no focused window in this module")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionCommitEvent(), FAILED, " + "there are no focused window in this module", + this)); return false; } if (!IsComposing()) { if (!aCommitString || aCommitString->IsEmpty()) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there is no composition and empty commit " - "string")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionCommitEvent(), FAILED, " + "there is no composition and empty commit string", + this)); return true; } - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" The composition wasn't started, force starting...")); + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p DispatchCompositionCommitEvent(), " + "the composition wasn't started, force starting...", + this)); nsCOMPtr kungFuDeathGrip(mLastFocusedWindow); if (!DispatchCompositionStart(aContext)) { return false; @@ -1315,9 +1367,11 @@ nsGtkIMModule::DispatchCompositionCommitEvent( if (lastFocusedWindow->IsDestroyed() || lastFocusedWindow != mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" NOTE, the focused widget was destroyed/changed by " - "compositioncommit event")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DispatchCompositionCommitEvent(), FAILED, " + "the focused widget was destroyed/changed by " + "compositioncommit event", + this)); return false; } @@ -1325,12 +1379,12 @@ nsGtkIMModule::DispatchCompositionCommitEvent( } already_AddRefed -nsGtkIMModule::CreateTextRangeArray(GtkIMContext* aContext, - const nsAString& aLastDispatchedData) +IMContextWrapper::CreateTextRangeArray(GtkIMContext* aContext, + const nsAString& aLastDispatchedData) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): CreateTextRangeArray, aContext=%p, " - "aLastDispatchedData=\"%s\" (length=%u)", + ("GTKIM: %p CreateTextRangeArray(aContext=%p, " + "aLastDispatchedData=\"%s\" (Length()=%u))", this, aContext, NS_ConvertUTF16toUTF8(aLastDispatchedData).get(), aLastDispatchedData.Length())); @@ -1342,8 +1396,10 @@ nsGtkIMModule::CreateTextRangeArray(GtkIMContext* aContext, gtk_im_context_get_preedit_string(aContext, &preedit_string, &feedback_list, &cursor_pos); if (!preedit_string || !*preedit_string) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" preedit_string is null")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p CreateTextRangeArray(), FAILED, due to " + "preedit_string is null", + this)); pango_attr_list_unref(feedback_list); g_free(preedit_string); return textRangeArray.forget(); @@ -1352,8 +1408,10 @@ nsGtkIMModule::CreateTextRangeArray(GtkIMContext* aContext, PangoAttrIterator* iter; iter = pango_attr_list_get_iterator(feedback_list); if (!iter) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, iterator couldn't be allocated")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p CreateTextRangeArray(), FAILED, iterator couldn't " + "be allocated", + this)); pango_attr_list_unref(feedback_list); g_free(preedit_string); return textRangeArray.forget(); @@ -1424,9 +1482,10 @@ nsGtkIMModule::CreateTextRangeArray(GtkIMContext* aContext, textRangeArray->AppendElement(range); - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" mStartOffset=%u, mEndOffset=%u, mRangeType=%s", - range.mStartOffset, range.mEndOffset, + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p CreateTextRangeArray(), mStartOffset=%u, " + "mEndOffset=%u, mRangeType=%s", + this, range.mStartOffset, range.mEndOffset, GetRangeTypeName(range.mRangeType))); } while (pango_attr_iterator_next(iter)); @@ -1442,9 +1501,10 @@ nsGtkIMModule::CreateTextRangeArray(GtkIMContext* aContext, range.mRangeType = NS_TEXTRANGE_CARETPOSITION; textRangeArray->AppendElement(range); - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" mStartOffset=%u, mEndOffset=%u, mRangeType=%s", - range.mStartOffset, range.mEndOffset, + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p CreateTextRangeArray(), mStartOffset=%u, mEndOffset=%u, " + "mRangeType=%s", + this, range.mStartOffset, range.mEndOffset, GetRangeTypeName(range.mRangeType))); pango_attr_iterator_destroy(iter); @@ -1455,10 +1515,10 @@ nsGtkIMModule::CreateTextRangeArray(GtkIMContext* aContext, } void -nsGtkIMModule::SetCursorPosition(GtkIMContext* aContext) +IMContextWrapper::SetCursorPosition(GtkIMContext* aContext) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): SetCursorPosition, aContext=%p, " + ("GTKIM: %p SetCursorPosition(aContext=%p), " "mCompositionTargetRange={ mOffset=%u, mLength=%u }" "mSelection={ mOffset=%u, mLength=%u, mWritingMode=%s }", this, aContext, mCompositionTargetRange.mOffset, @@ -1469,23 +1529,27 @@ nsGtkIMModule::SetCursorPosition(GtkIMContext* aContext) bool useCaret = false; if (!mCompositionTargetRange.IsValid()) { if (!mSelection.IsValid()) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, mCompositionTargetRange and mSelection are " - "invalid")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p SetCursorPosition(), FAILED, " + "mCompositionTargetRange and mSelection are invalid", + this)); return; } useCaret = true; } if (!mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no focused window")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p SetCursorPosition(), FAILED, due to no focused " + "window", + this)); return; } if (MOZ_UNLIKELY(!aContext)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no context")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p SetCursorPosition(), FAILED, due to no context", + this)); return; } @@ -1511,9 +1575,9 @@ nsGtkIMModule::SetCursorPosition(GtkIMContext* aContext) nsEventStatus status; mLastFocusedWindow->DispatchEvent(&charRect, status); if (!charRect.mSucceeded) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, %s was failed", - useCaret ? "NS_QUERY_CARET_RECT" : "NS_QUERY_TEXT_RECT")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p SetCursorPosition(), FAILED, %s was failed", + this, useCaret ? "NS_QUERY_CARET_RECT" : "NS_QUERY_TEXT_RECT")); return; } @@ -1521,33 +1585,33 @@ nsGtkIMModule::SetCursorPosition(GtkIMContext* aContext) static_cast(mLastFocusedWindow->GetTopLevelWidget()); // Get the position of the rootWindow in screen. - gint rootX, rootY; - gdk_window_get_origin(rootWindow->GetGdkWindow(), &rootX, &rootY); + LayoutDeviceIntPoint root = rootWindow->WidgetToScreenOffset(); // Get the position of IM context owner window in screen. - gint ownerX, ownerY; - gdk_window_get_origin(mOwnerWindow->GetGdkWindow(), &ownerX, &ownerY); + LayoutDeviceIntPoint owner = mOwnerWindow->WidgetToScreenOffset(); // Compute the caret position in the IM owner window. - GdkRectangle area; - area.x = charRect.mReply.mRect.x + rootX - ownerX; - area.y = charRect.mReply.mRect.y + rootY - ownerY; - area.width = 0; - area.height = charRect.mReply.mRect.height; + LayoutDeviceIntRect rect = charRect.mReply.mRect + root - owner; + rect.width = 0; + GdkRectangle area = rootWindow->DevicePixelsToGdkRectRoundOut( + LayoutDeviceIntRect::ToUntyped(rect)); gtk_im_context_set_cursor_location(aContext, &area); } nsresult -nsGtkIMModule::GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos) +IMContextWrapper::GetCurrentParagraph(nsAString& aText, + uint32_t& aCursorPos) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): GetCurrentParagraph, mCompositionState=%s", + ("GTKIM: %p GetCurrentParagraph(), mCompositionState=%s", this, GetCompositionStateName())); if (!mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no focused window in this module")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p GetCurrentParagraph(), FAILED, there are no " + "focused window in this module", + this)); return NS_ERROR_NULL_POINTER; } @@ -1561,8 +1625,10 @@ nsGtkIMModule::GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos) if (!EditorHasCompositionString()) { // Query cursor position & selection if (NS_WARN_IF(!EnsureToCacheSelection())) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, due to no valid selection information")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p GetCurrentParagraph(), FAILED, due to no " + "valid selection information", + this)); return NS_ERROR_FAILURE; } @@ -1570,17 +1636,19 @@ nsGtkIMModule::GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos) selLength = mSelection.mLength; } - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" selOffset=%u, selLength=%u", - selOffset, selLength)); + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p GetCurrentParagraph(), selOffset=%u, selLength=%u", + this, selOffset, selLength)); // XXX nsString::Find and nsString::RFind take int32_t for offset, so, // we cannot support this request when the current offset is larger // than INT32_MAX. if (selOffset > INT32_MAX || selLength > INT32_MAX || selOffset + selLength > INT32_MAX) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, The selection is out of range")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p GetCurrentParagraph(), FAILED, The selection is " + "out of range", + this)); return NS_ERROR_FAILURE; } @@ -1594,9 +1662,10 @@ nsGtkIMModule::GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos) nsAutoString textContent(queryTextContentEvent.mReply.mString); if (selOffset + selLength > textContent.Length()) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, The selection is invalid, textContent.Length()=%u", - textContent.Length())); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p GetCurrentParagraph(), FAILED, The selection is " + "invalid, textContent.Length()=%u", + this, textContent.Length())); return NS_ERROR_FAILURE; } @@ -1619,33 +1688,37 @@ nsGtkIMModule::GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos) aText = nsDependentSubstring(textContent, parStart, parEnd - parStart); aCursorPos = selOffset - uint32_t(parStart); - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" aText=%s, aText.Length()=%u, aCursorPos=%u", - NS_ConvertUTF16toUTF8(aText).get(), + MOZ_LOG(gGtkIMLog, LogLevel::Debug, + ("GTKIM: %p GetCurrentParagraph(), succeeded, aText=%s, " + "aText.Length()=%u, aCursorPos=%u", + this, NS_ConvertUTF16toUTF8(aText).get(), aText.Length(), aCursorPos)); return NS_OK; } nsresult -nsGtkIMModule::DeleteText(GtkIMContext* aContext, - int32_t aOffset, - uint32_t aNChars) +IMContextWrapper::DeleteText(GtkIMContext* aContext, + int32_t aOffset, + uint32_t aNChars) { MOZ_LOG(gGtkIMLog, LogLevel::Info, - ("GtkIMModule(%p): DeleteText, aContext=%p, aOffset=%d, aNChars=%d, " + ("GTKIM: %p DeleteText(aContext=%p, aOffset=%d, aNChars=%d), " "mCompositionState=%s", this, aContext, aOffset, aNChars, GetCompositionStateName())); if (!mLastFocusedWindow) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there are no focused window in this module")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, there are no focused window " + "in this module", + this)); return NS_ERROR_NULL_POINTER; } if (!aNChars) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, aNChars must not be zero")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, aNChars must not be zero", + this)); return NS_ERROR_INVALID_ARG; } @@ -1660,14 +1733,17 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext, if (wasComposing) { selOffset = mCompositionStart; if (!DispatchCompositionCommitEvent(aContext, &mSelectedString)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, quitting from DeletText")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, quitting from DeletText", + this)); return NS_ERROR_FAILURE; } } else { if (NS_WARN_IF(!EnsureToCacheSelection())) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, due to no valid selection information")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, due to no valid selection " + "information", + this)); return NS_ERROR_FAILURE; } selOffset = mSelection.mOffset; @@ -1681,8 +1757,9 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext, mLastFocusedWindow->DispatchEvent(&queryTextContentEvent, status); NS_ENSURE_TRUE(queryTextContentEvent.mSucceeded, NS_ERROR_FAILURE); if (queryTextContentEvent.mReply.mString.IsEmpty()) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, there is no contents")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, there is no contents", + this)); return NS_ERROR_FAILURE; } @@ -1692,10 +1769,10 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext, glong offsetInUTF8Characters = g_utf8_strlen(utf8Str.get(), utf8Str.Length()) + aOffset; if (offsetInUTF8Characters < 0) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, aOffset is too small for current cursor pos " - "(computed offset: %d)", - offsetInUTF8Characters)); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, aOffset is too small for " + "current cursor pos (computed offset: %d)", + this, offsetInUTF8Characters)); return NS_ERROR_FAILURE; } @@ -1707,10 +1784,10 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext, glong endInUTF8Characters = offsetInUTF8Characters + aNChars; if (countOfCharactersInUTF8 < endInUTF8Characters) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, aNChars is too large for current contents " - "(content length: %d, computed end offset: %d)", - countOfCharactersInUTF8, endInUTF8Characters)); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, aNChars is too large for " + "current contents (content length: %d, computed end offset: %d)", + this, countOfCharactersInUTF8, endInUTF8Characters)); return NS_ERROR_FAILURE; } @@ -1741,9 +1818,10 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext, if (!selectionEvent.mSucceeded || lastFocusedWindow != mLastFocusedWindow || lastFocusedWindow->Destroyed()) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, setting selection caused focus change " - "or window destroyed")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, setting selection caused " + "focus change or window destroyed", + this)); return NS_ERROR_FAILURE; } @@ -1756,9 +1834,10 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext, if (!contentCommandEvent.mSucceeded || lastFocusedWindow != mLastFocusedWindow || lastFocusedWindow->Destroyed()) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, deleting the selection caused focus change " - "or window destroyed")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, deleting the selection caused " + "focus change or window destroyed", + this)); return NS_ERROR_FAILURE; } @@ -1768,8 +1847,9 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext, // Restore the composition at new caret position. if (!DispatchCompositionStart(aContext)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, resterting composition start")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, resterting composition start", + this)); return NS_ERROR_FAILURE; } @@ -1780,8 +1860,9 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext, nsAutoString compositionString; GetCompositionString(aContext, compositionString); if (!DispatchCompositionChangeEvent(aContext, compositionString)) { - MOZ_LOG(gGtkIMLog, LogLevel::Info, - (" FAILED, restoring composition string")); + MOZ_LOG(gGtkIMLog, LogLevel::Error, + ("GTKIM: %p DeleteText(), FAILED, restoring composition string", + this)); return NS_ERROR_FAILURE; } @@ -1789,13 +1870,13 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext, } void -nsGtkIMModule::InitEvent(WidgetGUIEvent& aEvent) +IMContextWrapper::InitEvent(WidgetGUIEvent& aEvent) { aEvent.time = PR_Now() / 1000; } bool -nsGtkIMModule::EnsureToCacheSelection(nsAString* aSelectedString) +IMContextWrapper::EnsureToCacheSelection(nsAString* aSelectedString) { if (aSelectedString) { aSelectedString->Truncate(); @@ -1808,8 +1889,9 @@ nsGtkIMModule::EnsureToCacheSelection(nsAString* aSelectedString) if (NS_WARN_IF(!mLastFocusedWindow)) { MOZ_LOG(gGtkIMLog, LogLevel::Error, - ("GtkIMModule(%p): EnsureToCacheSelection(), FAILED, due to " - "no focused window", this)); + ("GTKIM: %p EnsureToCacheSelection(), FAILED, due to " + "no focused window", + this)); return false; } @@ -1820,16 +1902,18 @@ nsGtkIMModule::EnsureToCacheSelection(nsAString* aSelectedString) mLastFocusedWindow->DispatchEvent(&selection, status); if (NS_WARN_IF(!selection.mSucceeded)) { MOZ_LOG(gGtkIMLog, LogLevel::Error, - ("GtkIMModule(%p): EnsureToCacheSelection(), FAILED, due to " - "failure of query selection event", this)); + ("GTKIM: %p EnsureToCacheSelection(), FAILED, due to " + "failure of query selection event", + this)); return false; } mSelection.Assign(selection); if (!mSelection.IsValid()) { MOZ_LOG(gGtkIMLog, LogLevel::Error, - ("GtkIMModule(%p): EnsureToCacheSelection(), FAILED, due to " - "failure of query selection event (invalid result)", this)); + ("GTKIM: %p EnsureToCacheSelection(), FAILED, due to " + "failure of query selection event (invalid result)", + this)); return false; } @@ -1838,7 +1922,7 @@ nsGtkIMModule::EnsureToCacheSelection(nsAString* aSelectedString) } MOZ_LOG(gGtkIMLog, LogLevel::Debug, - ("GtkIMModule(%p): EnsureToCacheSelection(), Succeeded, mSelection=" + ("GTKIM: %p EnsureToCacheSelection(), Succeeded, mSelection=" "{ mOffset=%u, mLength=%u, mWritingMode=%s }", this, mSelection.mOffset, mSelection.mLength, GetWritingModeName(mSelection.mWritingMode).get())); @@ -1846,11 +1930,11 @@ nsGtkIMModule::EnsureToCacheSelection(nsAString* aSelectedString) } /****************************************************************************** - * nsGtkIMModule::Selection + * IMContextWrapper::Selection ******************************************************************************/ void -nsGtkIMModule::Selection::Assign(const IMENotification& aIMENotification) +IMContextWrapper::Selection::Assign(const IMENotification& aIMENotification) { MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE); mOffset = aIMENotification.mSelectionChangeData.mOffset; @@ -1859,7 +1943,7 @@ nsGtkIMModule::Selection::Assign(const IMENotification& aIMENotification) } void -nsGtkIMModule::Selection::Assign(const WidgetQueryContentEvent& aEvent) +IMContextWrapper::Selection::Assign(const WidgetQueryContentEvent& aEvent) { MOZ_ASSERT(aEvent.message == NS_QUERY_SELECTED_TEXT); MOZ_ASSERT(aEvent.mSucceeded); @@ -1867,3 +1951,6 @@ nsGtkIMModule::Selection::Assign(const WidgetQueryContentEvent& aEvent) mLength = aEvent.mReply.mString.Length(); mWritingMode = aEvent.GetWritingMode(); } + +} // namespace widget +} // namespace mozilla diff --git a/widget/gtk/nsGtkIMModule.h b/widget/gtk/IMContextWrapper.h similarity index 84% rename from widget/gtk/nsGtkIMModule.h rename to widget/gtk/IMContextWrapper.h index 4740b80a051..ba2db599571 100644 --- a/widget/gtk/nsGtkIMModule.h +++ b/widget/gtk/IMContextWrapper.h @@ -5,8 +5,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef __nsGtkIMModule_h__ -#define __nsGtkIMModule_h__ +#ifndef IMContextWrapper_h_ +#define IMContextWrapper_h_ #include #include @@ -22,20 +22,18 @@ class nsWindow; -class nsGtkIMModule -{ -protected: - typedef mozilla::widget::IMENotification IMENotification; - typedef mozilla::widget::InputContext InputContext; - typedef mozilla::widget::InputContextAction InputContextAction; +namespace mozilla { +namespace widget { +class IMContextWrapper final +{ public: // aOwnerWindow is a pointer of the owner window. When aOwnerWindow is // destroyed, the related IME contexts are released (i.e., IME cannot be // used with the instance after that). - explicit nsGtkIMModule(nsWindow* aOwnerWindow); + explicit IMContextWrapper(nsWindow* aOwnerWindow); - NS_INLINE_DECL_REFCOUNTING(nsGtkIMModule) + NS_INLINE_DECL_REFCOUNTING(IMContextWrapper) // "Enabled" means the users can use all IMEs. // I.e., the focus is in the normal editors. @@ -72,7 +70,7 @@ public: void OnLayoutChange(); protected: - ~nsGtkIMModule(); + ~IMContextWrapper(); // Owner of an instance of this class. This should be top level window. // The owner window must release the contexts when it's destroyed because @@ -205,7 +203,7 @@ protected: { uint32_t mOffset; uint32_t mLength; - mozilla::WritingMode mWritingMode; + WritingMode mWritingMode; Selection() : mOffset(UINT32_MAX) @@ -217,11 +215,11 @@ protected: { mOffset = UINT32_MAX; mLength = UINT32_MAX; - mWritingMode = mozilla::WritingMode(); + mWritingMode = WritingMode(); } void Assign(const IMENotification& aIMENotification); - void Assign(const mozilla::WidgetQueryContentEvent& aSelectedTextEvent); + void Assign(const WidgetQueryContentEvent& aSelectedTextEvent); bool IsValid() const { return mOffset != UINT32_MAX; } bool Collapsed() const { return !mLength; } @@ -230,8 +228,8 @@ protected: if (NS_WARN_IF(!IsValid())) { return UINT32_MAX; } - mozilla::CheckedInt endOffset = - mozilla::CheckedInt(mOffset) + mLength; + CheckedInt endOffset = + CheckedInt(mOffset) + mLength; if (NS_WARN_IF(!endOffset.isValid())) { return UINT32_MAX; } @@ -264,10 +262,10 @@ protected: // before key down bool mSetCursorPositionOnKeyEvent; - // sLastFocusedModule is a pointer to the last focused instance of this - // class. When a instance is destroyed and sLastFocusedModule refers it, + // sLastFocusedContext is a pointer to the last focused instance of this + // class. When a instance is destroyed and sLastFocusedContext refers it, // this is cleared. So, this refers valid pointer always. - static nsGtkIMModule* sLastFocusedModule; + static IMContextWrapper* sLastFocusedContext; // sUseSimpleContext indeicates if password editors and editors with // |ime-mode: disabled;| should use GtkIMContextSimple. @@ -276,32 +274,32 @@ protected: // Callback methods for native IME events. These methods should call // the related instance methods simply. - static gboolean OnRetrieveSurroundingCallback(GtkIMContext *aContext, - nsGtkIMModule *aModule); - static gboolean OnDeleteSurroundingCallback(GtkIMContext *aContext, - gint aOffset, - gint aNChars, - nsGtkIMModule *aModule); - static void OnCommitCompositionCallback(GtkIMContext *aContext, - const gchar *aString, - nsGtkIMModule* aModule); - static void OnChangeCompositionCallback(GtkIMContext *aContext, - nsGtkIMModule* aModule); - static void OnStartCompositionCallback(GtkIMContext *aContext, - nsGtkIMModule* aModule); - static void OnEndCompositionCallback(GtkIMContext *aContext, - nsGtkIMModule* aModule); + static gboolean OnRetrieveSurroundingCallback(GtkIMContext* aContext, + IMContextWrapper* aModule); + static gboolean OnDeleteSurroundingCallback(GtkIMContext* aContext, + gint aOffset, + gint aNChars, + IMContextWrapper* aModule); + static void OnCommitCompositionCallback(GtkIMContext* aContext, + const gchar* aString, + IMContextWrapper* aModule); + static void OnChangeCompositionCallback(GtkIMContext* aContext, + IMContextWrapper* aModule); + static void OnStartCompositionCallback(GtkIMContext* aContext, + IMContextWrapper* aModule); + static void OnEndCompositionCallback(GtkIMContext* aContext, + IMContextWrapper* aModule); // The instance methods for the native IME events. - gboolean OnRetrieveSurroundingNative(GtkIMContext *aContext); - gboolean OnDeleteSurroundingNative(GtkIMContext *aContext, - gint aOffset, - gint aNChars); - void OnCommitCompositionNative(GtkIMContext *aContext, - const gchar *aString); - void OnChangeCompositionNative(GtkIMContext *aContext); - void OnStartCompositionNative(GtkIMContext *aContext); - void OnEndCompositionNative(GtkIMContext *aContext); + gboolean OnRetrieveSurroundingNative(GtkIMContext* aContext); + gboolean OnDeleteSurroundingNative(GtkIMContext* aContext, + gint aOffset, + gint aNChars); + void OnCommitCompositionNative(GtkIMContext* aContext, + const gchar* aString); + void OnChangeCompositionNative(GtkIMContext* aContext); + void OnStartCompositionNative(GtkIMContext* aContext); + void OnEndCompositionNative(GtkIMContext* aContext); /** * GetCurrentContext() returns current IM context which is chosen with the @@ -349,7 +347,7 @@ protected: * of current composition. This should be * mDispatchedCompositionString. */ - already_AddRefed + already_AddRefed CreateTextRangeArray(GtkIMContext* aContext, const nsAString& aLastDispatchedData); @@ -379,10 +377,10 @@ protected: uint32_t aNChars); // Initializes the GUI event. - void InitEvent(mozilla::WidgetGUIEvent& aEvent); + void InitEvent(WidgetGUIEvent& aEvent); // Called before destroying the context to work around some platform bugs. - void PrepareToDestroyContext(GtkIMContext *aContext); + void PrepareToDestroyContext(GtkIMContext* aContext); /** * WARNING: @@ -430,4 +428,7 @@ protected: const nsAString* aCommitString = nullptr); }; -#endif // __nsGtkIMModule_h__ +} // namespace widget +} // namespace mozilla + +#endif // #ifndef IMContextWrapper_h_ diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build index 0861f92ced4..320478ab775 100644 --- a/widget/gtk/moz.build +++ b/widget/gtk/moz.build @@ -14,13 +14,13 @@ EXPORTS += [ ] UNIFIED_SOURCES += [ + 'IMContextWrapper.cpp', 'mozcontainer.c', 'NativeKeyBindings.cpp', 'nsAppShell.cpp', 'nsBidiKeyboard.cpp', 'nsColorPicker.cpp', 'nsFilePicker.cpp', - 'nsGtkIMModule.cpp', 'nsGtkKeyUtils.cpp', 'nsImageToPixbuf.cpp', 'nsLookAndFeel.cpp', diff --git a/widget/gtk/nsGtkKeyUtils.cpp b/widget/gtk/nsGtkKeyUtils.cpp index 85cca5e77ad..cbbd1972dbd 100644 --- a/widget/gtk/nsGtkKeyUtils.cpp +++ b/widget/gtk/nsGtkKeyUtils.cpp @@ -19,6 +19,7 @@ #include #include "WidgetUtils.h" #include "keysym2ucs.h" +#include "nsGtkUtils.h" #include "nsIBidiKeyboard.h" #include "nsServiceManagerUtils.h" diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 15ffdafc0b9..d6288b00d18 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -632,8 +632,8 @@ nsWindow::Destroy(void) NativeShow(false); - if (mIMModule) { - mIMModule->OnDestroyWindow(this); + if (mIMContext) { + mIMContext->OnDestroyWindow(this); } // make sure that we remove ourself as the focus window @@ -1367,8 +1367,8 @@ nsWindow::SetFocus(bool aRaise) // Set this window to be the focused child window gFocusWindow = this; - if (mIMModule) { - mIMModule->OnFocusWindow(this); + if (mIMContext) { + mIMContext->OnFocusWindow(this); } LOGFOCUS((" widget now has focus in SetFocus() [%p]\n", @@ -2793,8 +2793,8 @@ nsWindow::OnContainerFocusOutEvent(GdkEventFocus *aEvent) if (gFocusWindow) { nsRefPtr kungFuDeathGrip = gFocusWindow; - if (gFocusWindow->mIMModule) { - gFocusWindow->mIMModule->OnBlurWindow(gFocusWindow); + if (gFocusWindow->mIMContext) { + gFocusWindow->mIMContext->OnBlurWindow(gFocusWindow); } gFocusWindow = nullptr; } @@ -2857,9 +2857,9 @@ nsWindow::OnKeyPressEvent(GdkEventKey *aEvent) // if we are in the middle of composing text, XIM gets to see it // before mozilla does. bool IMEWasEnabled = false; - if (mIMModule) { - IMEWasEnabled = mIMModule->IsEnabled(); - if (mIMModule->OnKeyEvent(this, aEvent)) { + if (mIMContext) { + IMEWasEnabled = mIMContext->IsEnabled(); + if (mIMContext->OnKeyEvent(this, aEvent)) { return TRUE; } } @@ -2888,10 +2888,10 @@ nsWindow::OnKeyPressEvent(GdkEventKey *aEvent) // If a keydown event handler causes to enable IME, i.e., it moves // focus from IME unusable content to IME usable editor, we should // send the native key event to IME for the first input on the editor. - if (!IMEWasEnabled && mIMModule && mIMModule->IsEnabled()) { + if (!IMEWasEnabled && mIMContext && mIMContext->IsEnabled()) { // Notice our keydown event was already dispatched. This prevents // unnecessary DOM keydown event in the editor. - if (mIMModule->OnKeyEvent(this, aEvent, true)) { + if (mIMContext->OnKeyEvent(this, aEvent, true)) { return TRUE; } } @@ -2989,7 +2989,7 @@ nsWindow::OnKeyReleaseEvent(GdkEventKey *aEvent) { LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this)); - if (mIMModule && mIMModule->OnKeyEvent(this, aEvent)) { + if (mIMContext && mIMContext->OnKeyEvent(this, aEvent)) { return TRUE; } @@ -3660,12 +3660,12 @@ nsWindow::Create(nsIWidget *aParent, // We create input contexts for all containers, except for // toplevel popup windows if (mWindowType != eWindowType_popup) { - mIMModule = new nsGtkIMModule(this); + mIMContext = new IMContextWrapper(this); } - } else if (!mIMModule) { + } else if (!mIMContext) { nsWindow *container = GetContainerWindow(); if (container) { - mIMModule = container->mIMModule; + mIMContext = container->mIMContext; } } @@ -5970,27 +5970,27 @@ nsChildWindow::~nsChildWindow() nsresult nsWindow::NotifyIMEInternal(const IMENotification& aIMENotification) { - if (MOZ_UNLIKELY(!mIMModule)) { + if (MOZ_UNLIKELY(!mIMContext)) { return NS_ERROR_NOT_AVAILABLE; } switch (aIMENotification.mMessage) { case REQUEST_TO_COMMIT_COMPOSITION: case REQUEST_TO_CANCEL_COMPOSITION: - return mIMModule->EndIMEComposition(this); + return mIMContext->EndIMEComposition(this); case NOTIFY_IME_OF_FOCUS: - mIMModule->OnFocusChangeInGecko(true); + mIMContext->OnFocusChangeInGecko(true); return NS_OK; case NOTIFY_IME_OF_BLUR: - mIMModule->OnFocusChangeInGecko(false); + mIMContext->OnFocusChangeInGecko(false); return NS_OK; case NOTIFY_IME_OF_POSITION_CHANGE: - mIMModule->OnLayoutChange(); + mIMContext->OnLayoutChange(); return NS_OK; case NOTIFY_IME_OF_COMPOSITION_UPDATE: - mIMModule->OnUpdateComposition(); + mIMContext->OnUpdateComposition(); return NS_OK; case NOTIFY_IME_OF_SELECTION_CHANGE: - mIMModule->OnSelectionChange(this, aIMENotification); + mIMContext->OnSelectionChange(this, aIMENotification); return NS_OK; default: return NS_ERROR_NOT_IMPLEMENTED; @@ -6001,17 +6001,17 @@ NS_IMETHODIMP_(void) nsWindow::SetInputContext(const InputContext& aContext, const InputContextAction& aAction) { - if (!mIMModule) { + if (!mIMContext) { return; } - mIMModule->SetInputContext(this, &aContext, &aAction); + mIMContext->SetInputContext(this, &aContext, &aAction); } NS_IMETHODIMP_(InputContext) nsWindow::GetInputContext() { InputContext context; - if (!mIMModule) { + if (!mIMContext) { context.mIMEState.mEnabled = IMEState::DISABLED; context.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED; // If IME context isn't available on this widget, we should set |this| @@ -6019,8 +6019,8 @@ nsWindow::GetInputContext() // context per process. context.mNativeIMEContext = this; } else { - context = mIMModule->GetInputContext(); - context.mNativeIMEContext = mIMModule; + context = mIMContext->GetInputContext(); + context.mNativeIMEContext = mIMContext; } return context; } diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index 59656e40c64..8ebee70f6af 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -31,7 +31,7 @@ #endif #include "mozilla/EventForwards.h" -#include "nsGtkIMModule.h" +#include "IMContextWrapper.h" #undef LOG #ifdef MOZ_LOGGING @@ -166,6 +166,8 @@ public: // value that can be passed to gdk_window_set_decorations gint ConvertBorderStyles(nsBorderStyle aStyle); + GdkRectangle DevicePixelsToGdkRectRoundOut(nsIntRect rect); + // event callbacks #if (MOZ_WIDGET_GTK == 2) gboolean OnExposeEvent(GdkEventExpose *aEvent); @@ -478,7 +480,7 @@ private: virtual int32_t RoundsWidgetCoordinatesTo() override; /** - * |mIMModule| takes all IME related stuff. + * |mIMContext| takes all IME related stuff. * * This is owned by the top-level nsWindow or the topmost child * nsWindow embedded in a non-Gecko widget. @@ -490,7 +492,7 @@ private: * level window is released, the children still have a valid pointer, * however, IME doesn't work at that time. */ - nsRefPtr mIMModule; + nsRefPtr mIMContext; // HiDPI scale conversion gint GdkScaleFactor(); @@ -499,7 +501,6 @@ private: gint DevicePixelsToGdkCoordRoundUp(int pixels); gint DevicePixelsToGdkCoordRoundDown(int pixels); GdkPoint DevicePixelsToGdkPointRoundDown(nsIntPoint point); - GdkRectangle DevicePixelsToGdkRectRoundOut(nsIntRect rect); GdkRectangle DevicePixelsToGdkSizeRoundUp(nsIntSize pixelSize); // From GDK diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 8e2edef8d5e..3bf9ec9c721 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -484,7 +484,7 @@ protected: * require the compositor to be destroyed before ~nsBaseWidget is * reached (This is the case with gtk2 for instance). */ - void DestroyCompositor(); + virtual void DestroyCompositor(); void DestroyLayerManager(); void FreeShutdownObserver(); diff --git a/widget/nsIGfxInfo.idl b/widget/nsIGfxInfo.idl index 1e76c22c897..5e6492b0bd8 100644 --- a/widget/nsIGfxInfo.idl +++ b/widget/nsIGfxInfo.idl @@ -8,7 +8,7 @@ /* NOTE: this interface is completely undesigned, not stable and likely to change */ -[scriptable, uuid(98690931-c9a5-4675-9ab4-90932ec32bf2)] +[scriptable, uuid(4b5ea59e-af89-44f7-8c1c-2dea47a170d1)] interface nsIGfxInfo : nsISupports { /* @@ -102,6 +102,10 @@ interface nsIGfxInfo : nsISupports const long FEATURE_HARDWARE_VIDEO_DECODING = 12; /* Whether Direct3D 11 is supported for ANGLE, starting in 38. */ const long FEATURE_DIRECT3D_11_ANGLE = 13; + /* Whether Webrtc Hardware acceleration is supported, starting in 42. */ + const long FEATURE_WEBRTC_HW_ACCELERATION_ENCODE = 14; + /* Whether Webrtc Hardware acceleration is supported, starting in 42. */ + const long FEATURE_WEBRTC_HW_ACCELERATION_DECODE = 15; /* * A set of return values from GetFeatureStatus diff --git a/widget/windows/IMMHandler.cpp b/widget/windows/IMMHandler.cpp index 0bd9331594e..2be682693e9 100644 --- a/widget/windows/IMMHandler.cpp +++ b/widget/windows/IMMHandler.cpp @@ -1248,6 +1248,7 @@ IMMHandler::HandleStartComposition(nsWindow* aWindow, AdjustCompositionFont(aContext, selection.mWritingMode); mCompositionStart = selection.mOffset; + mCursorPosition = NO_IME_CARET; WidgetCompositionEvent event(true, NS_COMPOSITION_START, aWindow); nsIntPoint point(0, 0); @@ -2096,23 +2097,63 @@ IMMHandler::GetCharacterRectOfSelectedTextAt(nsWindow* aWindow, return false; } - uint32_t offset = selection.mOffset + aOffset; - bool useCaretRect = selection.mString.IsEmpty(); - if (useCaretRect && ShouldDrawCompositionStringOurselves() && - mIsComposing && !mCompositionString.IsEmpty()) { - // There is not a normal selection, but we have composition string. - // XXX mnakano - Should we implement NS_QUERY_IME_SELECTED_TEXT? - useCaretRect = false; - if (mCursorPosition != NO_IME_CARET) { - uint32_t cursorPosition = - std::min(mCursorPosition, mCompositionString.Length()); - NS_ASSERTION(offset >= cursorPosition, "offset is less than cursorPosition!"); - offset -= cursorPosition; + // The base offset of aOffset is the start of composition string during + // composing or the start of selected string not during composing. + uint32_t baseOffset = + mIsComposing ? mCompositionStart : selection.mOffset; + + CheckedInt checkingOffset = + CheckedInt(baseOffset) + aOffset; + if (NS_WARN_IF(!checkingOffset.isValid()) || + checkingOffset.value() == UINT32_MAX) { + MOZ_LOG(gIMMLog, LogLevel::Error, + ("IMM: GetCharacterRectOfSelectedTextAt, FAILED, due to " + "aOffset is too large (aOffset=%u, baseOffset=%u, mIsComposing=%s)", + aOffset, baseOffset, GetBoolName(mIsComposing))); + return false; + } + + // If the offset is larger than the end of composition string or selected + // string, we should return false since such case must be a bug of the caller + // or the active IME. If it's an IME's bug, we need to set targetLength to + // aOffset. + uint32_t targetLength = + mIsComposing ? mCompositionString.Length() : selection.Length(); + if (NS_WARN_IF(aOffset > targetLength)) { + MOZ_LOG(gIMMLog, LogLevel::Error, + ("IMM: GetCharacterRectOfSelectedTextAt, FAILED, due to " + "aOffset is too large (aOffset=%u, targetLength=%u, mIsComposing=%s)", + aOffset, targetLength, GetBoolName(mIsComposing))); + return false; + } + + uint32_t offset = checkingOffset.value(); + + // If there is caret, we might be able to use caret rect. + uint32_t caretOffset = UINT32_MAX; + // There is a caret only when the normal selection is collapsed. + if (selection.Collapsed()) { + if (mIsComposing) { + // If it's composing, mCursorPosition is the offset to caret in + // the composition string. + if (mCursorPosition != NO_IME_CARET) { + MOZ_ASSERT(mCursorPosition >= 0); + caretOffset = mCompositionStart + mCursorPosition; + } else if (!ShouldDrawCompositionStringOurselves() || + mCompositionString.IsEmpty()) { + // Otherwise, if there is no composition string, we should assume that + // there is a caret at the start of composition string. + caretOffset = mCompositionStart; + } + } else { + // If there is no composition, the selection offset is the caret offset. + caretOffset = selection.mOffset; } } - nsIntRect r; - if (!useCaretRect) { + // If there is a caret and retrieving offset is same as the caret offset, + // we should use the caret rect. + if (offset != caretOffset) { WidgetQueryContentEvent charRect(true, NS_QUERY_TEXT_RECT, aWindow); charRect.InitForQueryTextRect(offset, 1); aWindow->InitEvent(charRect, &point); diff --git a/widget/windows/IMMHandler.h b/widget/windows/IMMHandler.h index bdde8f80c9a..c01a8a441cf 100644 --- a/widget/windows/IMMHandler.h +++ b/widget/windows/IMMHandler.h @@ -279,11 +279,39 @@ protected: const IMEContext& aContext); void SetIMERelatedWindowsPosOnPlugin(nsWindow* aWindow, const IMEContext& aContext); + /** + * GetCharacterRectOfSelectedTextAt() returns character rect of the offset + * from the selection start or the start of composition string if there is + * a composition. + * + * @param aWindow The window which has focus. + * @param aOffset Offset from the selection start or the start of + * composition string when there is a composition. + * This must be in the selection range or + * the composition string. + * @param aCharRect The result. + * @param aWritingMode The writing mode of current selection. When this + * is nullptr, this assumes that the selection is in + * horizontal writing mode. + * @return true if this succeeded to retrieve the rect. + * Otherwise, false. + */ bool GetCharacterRectOfSelectedTextAt( nsWindow* aWindow, uint32_t aOffset, nsIntRect& aCharRect, mozilla::WritingMode* aWritingMode = nullptr); + /** + * GetCaretRect() returns caret rect at current selection start. + * + * @param aWindow The window which has focus. + * @param aCaretRect The result. + * @param aWritingMode The writing mode of current selection. When this + * is nullptr, this assumes that the selection is in + * horizontal writing mode. + * @return true if this succeeded to retrieve the rect. + * Otherwise, false. + */ bool GetCaretRect(nsWindow* aWindow, nsIntRect& aCaretRect, mozilla::WritingMode* aWritingMode = nullptr); @@ -402,6 +430,7 @@ protected: mIsValid = false; } uint32_t Length() const { return mString.Length(); } + bool Collapsed() const { return !Length(); } bool IsValid() const; bool Update(const IMENotification& aIMENotification); diff --git a/widget/windows/TSFTextStore.cpp b/widget/windows/TSFTextStore.cpp index f76f1fd262d..21e3009fc65 100644 --- a/widget/windows/TSFTextStore.cpp +++ b/widget/windows/TSFTextStore.cpp @@ -1350,6 +1350,8 @@ TSFTextStore::Destroy() CommitCompositionInternal(false); } + MaybeDestroyNativeCaret(); + if (mSink) { MOZ_LOG(sTextStoreLog, LogLevel::Debug, ("TSF: 0x%p TSFTextStore::Destroy(), calling " @@ -1579,10 +1581,6 @@ TSFTextStore::RequestLock(DWORD dwLockFlags, void TSFTextStore::DidLockGranted() { - if (mNativeCaretIsCreated) { - ::DestroyCaret(); - mNativeCaretIsCreated = false; - } if (IsReadWriteLocked()) { // FreeCJ (TIP for Traditional Chinese) calls SetSelection() to set caret // to the start of composition string and insert a full width space for @@ -3517,10 +3515,6 @@ TSFTextStore::GetTextExt(TsViewCookie vcView, mComposition.IsComposing() && mComposition.mStart <= acpStart && mComposition.EndOffset() >= acpStart && mComposition.mStart <= acpEnd && mComposition.EndOffset() >= acpEnd) { - if (mNativeCaretIsCreated) { - ::DestroyCaret(); - mNativeCaretIsCreated = false; - } CreateNativeCaret(); } @@ -4555,6 +4549,16 @@ TSFTextStore::NotifyTSFOfLayoutChange(bool aFlush) { mPendingOnLayoutChange = false; + // Now, layout has been computed. We should notify mLockedContent for + // making GetTextExt() and GetACPFromPoint() not return TS_E_NOLAYOUT. + if (mLockedContent.IsInitialized()) { + mLockedContent.OnLayoutChanged(); + } + + // Now, the caret position is different from ours. Destroy the native caret + // if there is. + MaybeDestroyNativeCaret(); + // This method should return true if either way succeeds. bool ret = false; @@ -4678,6 +4682,8 @@ TSFTextStore::OnMouseButtonEventInternal( void TSFTextStore::CreateNativeCaret() { + MaybeDestroyNativeCaret(); + MOZ_LOG(sTextStoreLog, LogLevel::Debug, ("TSF: 0x%p TSFTextStore::CreateNativeCaret(), " "mComposition.IsComposing()=%s", @@ -4733,6 +4739,21 @@ TSFTextStore::CreateNativeCaret() ::SetCaretPos(caretRect.x, caretRect.y); } +void +TSFTextStore::MaybeDestroyNativeCaret() +{ + if (!mNativeCaretIsCreated) { + return; + } + + MOZ_LOG(sTextStoreLog, LogLevel::Debug, + ("TSF: 0x%p TSFTextStore::MaybeDestroyNativeCaret(), " + "destroying native caret", this)); + + ::DestroyCaret(); + mNativeCaretIsCreated = false; +} + void TSFTextStore::CommitCompositionInternal(bool aDiscard) { diff --git a/widget/windows/TSFTextStore.h b/widget/windows/TSFTextStore.h index 38b316ab130..7b7892e5318 100644 --- a/widget/windows/TSFTextStore.h +++ b/widget/windows/TSFTextStore.h @@ -306,6 +306,8 @@ protected: // Creates native caret over our caret. This method only works on desktop // application. Otherwise, this does nothing. void CreateNativeCaret(); + // Destroys native caret if there is. + void MaybeDestroyNativeCaret(); // Holds the pointer to our current win32 widget nsRefPtr mWidget; @@ -624,6 +626,11 @@ protected: mInitialized = true; } + void OnLayoutChanged() + { + mMinTextModifiedOffset = NOT_MODIFIED; + } + const nsDependentSubstring GetSelectedText() const; const nsDependentSubstring GetSubstring(uint32_t aStart, uint32_t aLength) const; diff --git a/xpcom/glue/nsTArray.h b/xpcom/glue/nsTArray.h index 14a27a7ea96..2809ad0c132 100644 --- a/xpcom/glue/nsTArray.h +++ b/xpcom/glue/nsTArray.h @@ -10,6 +10,7 @@ #include "nsTArrayForwardDeclare.h" #include "mozilla/Alignment.h" #include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" #include "mozilla/BinarySearch.h" #include "mozilla/fallible.h" #include "mozilla/MathAlgorithms.h" @@ -660,7 +661,7 @@ struct nsTArray_CopyWithConstructors // The default behaviour is to use memcpy/memmove for everything. // template -struct nsTArray_CopyChooser +struct MOZ_NEEDS_MEMMOVABLE_TYPE nsTArray_CopyChooser { typedef nsTArray_CopyWithMemutils Type; }; @@ -2187,7 +2188,7 @@ public: // You shouldn't use this class directly. // template -class nsAutoArrayBase : public TArrayBase +class MOZ_NON_MEMMOVABLE nsAutoArrayBase : public TArrayBase { static_assert(N != 0, "nsAutoArrayBase should be specialized"); public: diff --git a/xpcom/glue/nsTHashtable.h b/xpcom/glue/nsTHashtable.h index 94312181010..a89dad83f5a 100644 --- a/xpcom/glue/nsTHashtable.h +++ b/xpcom/glue/nsTHashtable.h @@ -16,6 +16,7 @@ #include "mozilla/Move.h" #include "mozilla/fallible.h" #include "mozilla/PodOperations.h" +#include "mozilla/Attributes.h" #include @@ -82,7 +83,7 @@ enum PLDHashOperator }; template -class nsTHashtable +class MOZ_NEEDS_NO_VTABLE_TYPE nsTHashtable { typedef mozilla::fallible_t fallible_t; diff --git a/xpcom/glue/pldhash.cpp b/xpcom/glue/pldhash.cpp index 5fcd463153e..e474e74ed49 100644 --- a/xpcom/glue/pldhash.cpp +++ b/xpcom/glue/pldhash.cpp @@ -4,9 +4,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* - * Double hashing implementation. - */ #include #include #include @@ -14,7 +11,6 @@ #include "pldhash.h" #include "mozilla/HashFunctions.h" #include "mozilla/MathAlgorithms.h" -#include "nsDebug.h" /* for PR_ASSERT */ #include "nsAlgorithm.h" #include "mozilla/Likely.h" #include "mozilla/MemoryReporting.h" @@ -95,7 +91,7 @@ PL_DHashMatchStringKey(PLDHashTable* aTable, { const PLDHashEntryStub* stub = (const PLDHashEntryStub*)aEntry; - /* XXX tolerate null keys on account of sloppy Mozilla callers. */ + // XXX tolerate null keys on account of sloppy Mozilla callers. return stub->key == aKey || (stub->key && aKey && strcmp((const char*)stub->key, (const char*)aKey) == 0); @@ -150,13 +146,11 @@ SizeOfEntryStore(uint32_t aCapacity, uint32_t aEntrySize, uint32_t* aNbytes) return uint64_t(*aNbytes) == nbytes64; // returns false on overflow } -/* - * Compute max and min load numbers (entry counts). We have a secondary max - * that allows us to overload a table reasonably if it cannot be grown further - * (i.e. if ChangeTable() fails). The table slows down drastically if the - * secondary max is too close to 1, but 0.96875 gives only a slight slowdown - * while allowing 1.3x more elements. - */ +// Compute max and min load numbers (entry counts). We have a secondary max +// that allows us to overload a table reasonably if it cannot be grown further +// (i.e. if ChangeTable() fails). The table slows down drastically if the +// secondary max is too close to 1, but 0.96875 gives only a slight slowdown +// while allowing 1.3x more elements. static inline uint32_t MaxLoad(uint32_t aCapacity) { @@ -288,14 +282,12 @@ PLDHashTable::Hash2(PLDHashNumber aHash, aSizeMaskOut = (PLDHashNumber(1) << sizeLog2) - 1; } -/* - * Reserve mKeyHash 0 for free entries and 1 for removed-entry sentinels. Note - * that a removed-entry sentinel need be stored only if the removed entry had - * a colliding entry added after it. Therefore we can use 1 as the collision - * flag in addition to the removed-entry sentinel value. Multiplicative hash - * uses the high order bits of mKeyHash, so this least-significant reservation - * should not hurt the hash function's effectiveness much. - */ +// Reserve mKeyHash 0 for free entries and 1 for removed-entry sentinels. Note +// that a removed-entry sentinel need be stored only if the removed entry had +// a colliding entry added after it. Therefore we can use 1 as the collision +// flag in addition to the removed-entry sentinel value. Multiplicative hash +// uses the high order bits of mKeyHash, so this least-significant reservation +// should not hurt the hash function's effectiveness much. /* static */ MOZ_ALWAYS_INLINE bool PLDHashTable::EntryIsFree(PLDHashEntryHdr* aEntry) @@ -324,14 +316,14 @@ PLDHashTable::MarkEntryRemoved(PLDHashEntryHdr* aEntry) aEntry->mKeyHash = 1; } -/* Match an entry's mKeyHash against an unstored one computed from a key. */ +// Match an entry's mKeyHash against an unstored one computed from a key. /* static */ bool PLDHashTable::MatchEntryKeyhash(PLDHashEntryHdr* aEntry, PLDHashNumber aKeyHash) { return (aEntry->mKeyHash & ~kCollisionFlag) == aKeyHash; } -/* Compute the address of the indexed entry in table. */ +// Compute the address of the indexed entry in table. PLDHashEntryHdr* PLDHashTable::AddressEntry(uint32_t aIndex) { @@ -348,7 +340,7 @@ PLDHashTable::~PLDHashTable() return; } - /* Clear any remaining live entries. */ + // Clear any remaining live entries. char* entryAddr = mEntryStore; char* entryLimit = entryAddr + Capacity() * mEntrySize; while (entryAddr < entryLimit) { @@ -359,7 +351,7 @@ PLDHashTable::~PLDHashTable() entryAddr += mEntrySize; } - /* Free entry storage last. */ + // Free entry storage last. free(mEntryStore); mEntryStore = nullptr; } @@ -394,31 +386,29 @@ PLDHashTable::SearchTable(const void* aKey, PLDHashNumber aKeyHash) NS_ASSERTION(!(aKeyHash & kCollisionFlag), "!(aKeyHash & kCollisionFlag)"); - /* Compute the primary hash address. */ + // Compute the primary hash address. PLDHashNumber hash1 = Hash1(aKeyHash); PLDHashEntryHdr* entry = AddressEntry(hash1); - /* Miss: return space for a new entry. */ + // Miss: return space for a new entry. if (EntryIsFree(entry)) { return (Reason == ForAdd) ? entry : nullptr; } - /* Hit: return entry. */ + // Hit: return entry. PLDHashMatchEntry matchEntry = mOps->matchEntry; if (MatchEntryKeyhash(entry, aKeyHash) && matchEntry(this, entry, aKey)) { return entry; } - /* Collision: double hash. */ + // Collision: double hash. PLDHashNumber hash2; uint32_t sizeMask; Hash2(aKeyHash, hash2, sizeMask); - /* - * Save the first removed entry pointer so Add() can recycle it. (Only used - * if Reason==ForAdd.) - */ + // Save the first removed entry pointer so Add() can recycle it. (Only used + // if Reason==ForAdd.) PLDHashEntryHdr* firstRemoved = nullptr; for (;;) { @@ -447,20 +437,17 @@ PLDHashTable::SearchTable(const void* aKey, PLDHashNumber aKeyHash) } } - /* NOTREACHED */ + // NOTREACHED return nullptr; } -/* - * This is a copy of SearchTable, used by ChangeTable, hardcoded to - * 1. assume |aIsAdd| is true, - * 2. assume that |aKey| will never match an existing entry, and - * 3. assume that no entries have been removed from the current table - * structure. - * Avoiding the need for |aKey| means we can avoid needing a way to map - * entries to keys, which means callers can use complex key types more - * easily. - */ +// This is a copy of SearchTable(), used by ChangeTable(), hardcoded to +// 1. assume |aIsAdd| is true, +// 2. assume that |aKey| will never match an existing entry, and +// 3. assume that no entries have been removed from the current table +// structure. +// Avoiding the need for |aKey| means we can avoid needing a way to map entries +// to keys, which means callers can use complex key types more easily. PLDHashEntryHdr* PL_DHASH_FASTCALL PLDHashTable::FindFreeEntry(PLDHashNumber aKeyHash) { @@ -468,16 +455,16 @@ PLDHashTable::FindFreeEntry(PLDHashNumber aKeyHash) NS_ASSERTION(!(aKeyHash & kCollisionFlag), "!(aKeyHash & kCollisionFlag)"); - /* Compute the primary hash address. */ + // Compute the primary hash address. PLDHashNumber hash1 = Hash1(aKeyHash); PLDHashEntryHdr* entry = AddressEntry(hash1); - /* Miss: return space for a new entry. */ + // Miss: return space for a new entry. if (EntryIsFree(entry)) { return entry; } - /* Collision: double hash. */ + // Collision: double hash. PLDHashNumber hash2; uint32_t sizeMask; Hash2(aKeyHash, hash2, sizeMask); @@ -496,7 +483,7 @@ PLDHashTable::FindFreeEntry(PLDHashNumber aKeyHash) } } - /* NOTREACHED */ + // NOTREACHED return nullptr; } @@ -505,7 +492,7 @@ PLDHashTable::ChangeTable(int32_t aDeltaLog2) { MOZ_ASSERT(mEntryStore); - /* Look, but don't touch, until we succeed in getting new entry store. */ + // Look, but don't touch, until we succeed in getting new entry store. int32_t oldLog2 = kHashBits - mHashShift; int32_t newLog2 = oldLog2 + aDeltaLog2; uint32_t newCapacity = 1u << newLog2; @@ -523,12 +510,12 @@ PLDHashTable::ChangeTable(int32_t aDeltaLog2) return false; } - /* We can't fail from here on, so update table parameters. */ + // We can't fail from here on, so update table parameters. mHashShift = kHashBits - newLog2; mRemovedCount = 0; mGeneration++; - /* Assign the new entry store to table. */ + // Assign the new entry store to table. memset(newEntryStore, 0, nbytes); char* oldEntryStore; char* oldEntryAddr; @@ -536,7 +523,7 @@ PLDHashTable::ChangeTable(int32_t aDeltaLog2) mEntryStore = newEntryStore; PLDHashMoveEntry moveEntry = mOps->moveEntry; - /* Copy only live entries, leaving removed ones behind. */ + // Copy only live entries, leaving removed ones behind. uint32_t oldCapacity = 1u << oldLog2; for (uint32_t i = 0; i < oldCapacity; ++i) { PLDHashEntryHdr* oldEntry = (PLDHashEntryHdr*)oldEntryAddr; @@ -562,7 +549,7 @@ PLDHashTable::ComputeKeyHash(const void* aKey) PLDHashNumber keyHash = mOps->hashKey(this, aKey); keyHash *= kGoldenRatio; - /* Avoid 0 and 1 hash codes, they indicate free and removed entries. */ + // Avoid 0 and 1 hash codes, they indicate free and removed entries. if (keyHash < 2) { keyHash -= 2; } @@ -605,14 +592,12 @@ PLDHashTable::Add(const void* aKey, const mozilla::fallible_t&) memset(mEntryStore, 0, nbytes); } - /* - * If alpha is >= .75, grow or compress the table. If aKey is already - * in the table, we may grow once more than necessary, but only if we - * are on the edge of being overloaded. - */ + // If alpha is >= .75, grow or compress the table. If aKey is already in the + // table, we may grow once more than necessary, but only if we are on the + // edge of being overloaded. uint32_t capacity = Capacity(); if (mEntryCount + mRemovedCount >= MaxLoad(capacity)) { - /* Compress if a quarter or more of all entries are removed. */ + // Compress if a quarter or more of all entries are removed. int deltaLog2; if (mRemovedCount >= capacity >> 2) { deltaLog2 = 0; @@ -620,25 +605,20 @@ PLDHashTable::Add(const void* aKey, const mozilla::fallible_t&) deltaLog2 = 1; } - /* - * Grow or compress the table. If ChangeTable() fails, allow - * overloading up to the secondary max. Once we hit the secondary - * max, return null. - */ + // Grow or compress the table. If ChangeTable() fails, allow overloading up + // to the secondary max. Once we hit the secondary max, return null. if (!ChangeTable(deltaLog2) && mEntryCount + mRemovedCount >= MaxLoadOnGrowthFailure(capacity)) { return nullptr; } } - /* - * Look for entry after possibly growing, so we don't have to add it, - * then skip it while growing the table and re-add it after. - */ + // Look for entry after possibly growing, so we don't have to add it, + // then skip it while growing the table and re-add it after. PLDHashNumber keyHash = ComputeKeyHash(aKey); PLDHashEntryHdr* entry = SearchTable(aKey, keyHash); if (!EntryIsLive(entry)) { - /* Initialize the entry, indicating that it's no longer free. */ + // Initialize the entry, indicating that it's no longer free. if (EntryIsRemoved(entry)) { mRemovedCount--; keyHash |= kCollisionFlag; @@ -685,10 +665,10 @@ PLDHashTable::Remove(const void* aKey) mEntryStore ? SearchTable(aKey, ComputeKeyHash(aKey)) : nullptr; if (entry) { - /* Clear this entry and mark it as "removed". */ - PL_DHashTableRawRemove(this, entry); + // Clear this entry and mark it as "removed". + RawRemove(entry); - /* Shrink if alpha is <= .25 and the table isn't too small already. */ + // Shrink if alpha is <= .25 and the table isn't too small already. uint32_t capacity = Capacity(); if (capacity > kMinCapacity && mEntryCount <= MinLoad(capacity)) { @@ -734,7 +714,7 @@ PLDHashTable::RawRemove(PLDHashEntryHdr* aEntry) NS_ASSERTION(EntryIsLive(aEntry), "EntryIsLive(aEntry)"); - /* Load keyHash first in case clearEntry() goofs it. */ + // Load keyHash first in case clearEntry() goofs it. PLDHashNumber keyHash = aEntry->mKeyHash; mOps->clearEntry(this, aEntry); if (keyHash & kCollisionFlag) { diff --git a/xpcom/glue/pldhash.h b/xpcom/glue/pldhash.h index 42c237fd950..025f5b8e0b5 100644 --- a/xpcom/glue/pldhash.h +++ b/xpcom/glue/pldhash.h @@ -6,9 +6,7 @@ #ifndef pldhash_h___ #define pldhash_h___ -/* - * Double hashing, a la Knuth 6. - */ + #include "mozilla/Atomics.h" #include "mozilla/Attributes.h" // for MOZ_ALWAYS_INLINE #include "mozilla/fallible.h" @@ -30,24 +28,22 @@ typedef uint32_t PLDHashNumber; class PLDHashTable; struct PLDHashTableOps; -/* - * Table entry header structure. - * - * In order to allow in-line allocation of key and value, we do not declare - * either here. Instead, the API uses const void *key as a formal parameter. - * The key need not be stored in the entry; it may be part of the value, but - * need not be stored at all. - * - * Callback types are defined below and grouped into the PLDHashTableOps - * structure, for single static initialization per hash table sub-type. - * - * Each hash table sub-type should make its entry type a subclass of - * PLDHashEntryHdr. The mKeyHash member contains the result of multiplying the - * hash code returned from the hashKey callback (see below) by kGoldenRatio, - * then constraining the result to avoid the magic 0 and 1 values. The stored - * mKeyHash value is table size invariant, and it is maintained automatically - * -- users need never access it. - */ +// Table entry header structure. +// +// In order to allow in-line allocation of key and value, we do not declare +// either here. Instead, the API uses const void *key as a formal parameter. +// The key need not be stored in the entry; it may be part of the value, but +// need not be stored at all. +// +// Callback types are defined below and grouped into the PLDHashTableOps +// structure, for single static initialization per hash table sub-type. +// +// Each hash table sub-type should make its entry type a subclass of +// PLDHashEntryHdr. The mKeyHash member contains the result of multiplying the +// hash code returned from the hashKey callback (see below) by kGoldenRatio, +// then constraining the result to avoid the magic 0 and 1 values. The stored +// mKeyHash value is table size invariant, and it is maintained automatically +// -- users need never access it. struct PLDHashEntryHdr { private: @@ -206,31 +202,29 @@ private: }; #endif -/* - * A PLDHashTable may be allocated on the stack or within another structure or - * class. No entry storage is allocated until the first element is added. This - * means that empty hash tables are cheap, which is good because they are - * common. - * - * There used to be a long, math-heavy comment here about the merits of - * double hashing vs. chaining; it was removed in bug 1058335. In short, double - * hashing is more space-efficient unless the element size gets large (in which - * case you should keep using double hashing but switch to using pointer - * elements). Also, with double hashing, you can't safely hold an entry pointer - * and use it after an ADD or REMOVE operation, unless you sample - * aTable->mGeneration before adding or removing, and compare the sample after, - * dereferencing the entry pointer only if aTable->mGeneration has not changed. - */ +// A PLDHashTable may be allocated on the stack or within another structure or +// class. No entry storage is allocated until the first element is added. This +// means that empty hash tables are cheap, which is good because they are +// common. +// +// There used to be a long, math-heavy comment here about the merits of +// double hashing vs. chaining; it was removed in bug 1058335. In short, double +// hashing is more space-efficient unless the element size gets large (in which +// case you should keep using double hashing but switch to using pointer +// elements). Also, with double hashing, you can't safely hold an entry pointer +// and use it after an ADD or REMOVE operation, unless you sample +// aTable->mGeneration before adding or removing, and compare the sample after, +// dereferencing the entry pointer only if aTable->mGeneration has not changed. class PLDHashTable { private: - const PLDHashTableOps* const mOps; /* Virtual operations; see below. */ - int16_t mHashShift; /* multiplicative hash shift */ - const uint32_t mEntrySize; /* number of bytes in an entry */ - uint32_t mEntryCount; /* number of entries in table */ - uint32_t mRemovedCount; /* removed entry sentinels in table */ - uint32_t mGeneration; /* entry storage generation number */ - char* mEntryStore; /* entry storage; allocated lazily */ + const PLDHashTableOps* const mOps; // Virtual operations; see below. + int16_t mHashShift; // Multiplicative hash shift. + const uint32_t mEntrySize; // Number of bytes in an entry. + uint32_t mEntryCount; // Number of entries in table. + uint32_t mRemovedCount; // Removed entry sentinels in table. + uint32_t mGeneration; // Entry storage generation number. + char* mEntryStore; // Entry storage; allocated lazily. #ifdef DEBUG mutable Checker mChecker; @@ -287,11 +281,9 @@ public: // This should be used rarely. const PLDHashTableOps* const Ops() { return mOps; } - /* - * Size in entries (gross, not net of free and removed sentinels) for table. - * This can be zero if no elements have been added yet, in which case the - * entry storage will not have yet been allocated. - */ + // Size in entries (gross, not net of free and removed sentinels) for table. + // This can be zero if no elements have been added yet, in which case the + // entry storage will not have yet been allocated. uint32_t Capacity() const { return mEntryStore ? CapacityFromHashShift() : 0; @@ -301,11 +293,43 @@ public: uint32_t EntryCount() const { return mEntryCount; } uint32_t Generation() const { return mGeneration; } + // To search for a |key| in |table|, call: + // + // entry = table.Search(key); + // + // If |entry| is non-null, |key| was found. If |entry| is null, key was not + // found. PLDHashEntryHdr* Search(const void* aKey); + + // To add an entry identified by |key| to table, call: + // + // entry = table.Add(key, mozilla::fallible); + // + // If |entry| is null upon return, then the table is severely overloaded and + // memory can't be allocated for entry storage. + // + // Otherwise, |aEntry->mKeyHash| has been set so that + // PLDHashTable::EntryIsFree(entry) is false, and it is up to the caller to + // initialize the key and value parts of the entry sub-type, if they have not + // been set already (i.e. if entry was not already in the table, and if the + // optional initEntry hook was not used). PLDHashEntryHdr* Add(const void* aKey, const mozilla::fallible_t&); + + // This is like the other Add() function, but infallible, and so never + // returns null. PLDHashEntryHdr* Add(const void* aKey); + + // To remove an entry identified by |key| from table, call: + // + // table.Remove(key); + // + // If |key|'s entry is found, it is cleared (via table->mOps->clearEntry). void Remove(const void* aKey); + // Remove an entry already accessed via Search() or Add(). + // + // NB: this is a "raw" or low-level method. It does not shrink the table if + // it is underloaded. Don't use it unless you know what you are doing. void RawRemove(PLDHashEntryHdr* aEntry); // This function is equivalent to @@ -322,15 +346,22 @@ public: // a new |aLength| argument. void ClearAndPrepareForLength(uint32_t aLength); + // Measure the size of the table's entry storage, and if + // |aSizeOfEntryExcludingThis| is non-nullptr, measure the size of things + // pointed to by entries. size_t SizeOfIncludingThis( PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis, mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr) const; + // Like SizeOfExcludingThis(), but includes sizeof(*this). size_t SizeOfExcludingThis( PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis, mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr) const; #ifdef DEBUG + // Mark a table as immutable for the remainder of its lifetime. This + // changes the implementation from asserting one set of invariants to + // asserting a different set. void MarkImmutable(); #endif @@ -456,208 +487,140 @@ private: PLDHashTable& operator=(const PLDHashTable& aOther) = delete; }; -/* - * Compute the hash code for a given key to be looked up, added, or removed - * from aTable. A hash code may have any PLDHashNumber value. - */ +// Compute the hash code for a given key to be looked up, added, or removed +// from aTable. A hash code may have any PLDHashNumber value. typedef PLDHashNumber (*PLDHashHashKey)(PLDHashTable* aTable, const void* aKey); -/* - * Compare the key identifying aEntry in aTable with the provided key parameter. - * Return true if keys match, false otherwise. - */ +// Compare the key identifying aEntry in aTable with the provided key parameter. +// Return true if keys match, false otherwise. typedef bool (*PLDHashMatchEntry)(PLDHashTable* aTable, const PLDHashEntryHdr* aEntry, const void* aKey); -/* - * Copy the data starting at aFrom to the new entry storage at aTo. Do not add - * reference counts for any strong references in the entry, however, as this - * is a "move" operation: the old entry storage at from will be freed without - * any reference-decrementing callback shortly. - */ +// Copy the data starting at aFrom to the new entry storage at aTo. Do not add +// reference counts for any strong references in the entry, however, as this +// is a "move" operation: the old entry storage at from will be freed without +// any reference-decrementing callback shortly. typedef void (*PLDHashMoveEntry)(PLDHashTable* aTable, const PLDHashEntryHdr* aFrom, PLDHashEntryHdr* aTo); -/* - * Clear the entry and drop any strong references it holds. This callback is - * invoked by PL_DHashTableRemove(), but only if the given key is found in the - * table. - */ +// Clear the entry and drop any strong references it holds. This callback is +// invoked by Remove(), but only if the given key is found in the table. typedef void (*PLDHashClearEntry)(PLDHashTable* aTable, PLDHashEntryHdr* aEntry); -/* - * Initialize a new entry, apart from mKeyHash. This function is called when - * PL_DHashTableAdd finds no existing entry for the given key, and must add a - * new one. At that point, aEntry->mKeyHash is not set yet, to avoid claiming - * the last free entry in a severely overloaded table. - */ +// Initialize a new entry, apart from mKeyHash. This function is called when +// Add() finds no existing entry for the given key, and must add a new one. At +// that point, |aEntry->mKeyHash| is not set yet, to avoid claiming the last +// free entry in a severely overloaded table. typedef void (*PLDHashInitEntry)(PLDHashEntryHdr* aEntry, const void* aKey); -/* - * Finally, the "vtable" structure for PLDHashTable. The first four hooks - * must be provided by implementations; they're called unconditionally by the - * generic pldhash.c code. Hooks after these may be null. - * - * Summary of allocation-related hook usage with C++ placement new emphasis: - * initEntry Call placement new using default key-based ctor. - * moveEntry Call placement new using copy ctor, run dtor on old - * entry storage. - * clearEntry Run dtor on entry. - * - * Note the reason why initEntry is optional: the default hooks (stubs) clear - * entry storage: On successful PL_DHashTableAdd(tbl, key), the returned entry - * pointer addresses an entry struct whose mKeyHash member has been set - * non-zero, but all other entry members are still clear (null). - * PL_DHashTableAdd callers can test such members to see whether the entry was - * newly created by the PL_DHashTableAdd call that just succeeded. If - * placement new or similar initialization is required, define an initEntry - * hook. Of course, the clearEntry hook must zero or null appropriately. - * - * XXX assumes 0 is null for pointer types. - */ +// Finally, the "vtable" structure for PLDHashTable. The first four hooks +// must be provided by implementations; they're called unconditionally by the +// generic pldhash.c code. Hooks after these may be null. +// +// Summary of allocation-related hook usage with C++ placement new emphasis: +// initEntry Call placement new using default key-based ctor. +// moveEntry Call placement new using copy ctor, run dtor on old +// entry storage. +// clearEntry Run dtor on entry. +// +// Note the reason why initEntry is optional: the default hooks (stubs) clear +// entry storage: On successful Add(tbl, key), the returned entry pointer +// addresses an entry struct whose mKeyHash member has been set non-zero, but +// all other entry members are still clear (null). Add() callers can test such +// members to see whether the entry was newly created by the Add() call that +// just succeeded. If placement new or similar initialization is required, +// define an |initEntry| hook. Of course, the |clearEntry| hook must zero or +// null appropriately. +// +// XXX assumes 0 is null for pointer types. struct PLDHashTableOps { - /* Mandatory hooks. All implementations must provide these. */ + // Mandatory hooks. All implementations must provide these. PLDHashHashKey hashKey; PLDHashMatchEntry matchEntry; PLDHashMoveEntry moveEntry; PLDHashClearEntry clearEntry; - /* Optional hooks start here. If null, these are not called. */ + // Optional hooks start here. If null, these are not called. PLDHashInitEntry initEntry; }; -/* - * Default implementations for the above mOps. - */ +// Default implementations for the above mOps. -PLDHashNumber PL_DHashStringKey(PLDHashTable* aTable, const void* aKey); +PLDHashNumber +PL_DHashStringKey(PLDHashTable* aTable, const void* aKey); -/* A minimal entry is a subclass of PLDHashEntryHdr and has void key pointer. */ +// A minimal entry is a subclass of PLDHashEntryHdr and has void key pointer. struct PLDHashEntryStub : public PLDHashEntryHdr { const void* key; }; -PLDHashNumber PL_DHashVoidPtrKeyStub(PLDHashTable* aTable, const void* aKey); +PLDHashNumber +PL_DHashVoidPtrKeyStub(PLDHashTable* aTable, const void* aKey); -bool PL_DHashMatchEntryStub(PLDHashTable* aTable, - const PLDHashEntryHdr* aEntry, - const void* aKey); +bool +PL_DHashMatchEntryStub(PLDHashTable* aTable, + const PLDHashEntryHdr* aEntry, + const void* aKey); -bool PL_DHashMatchStringKey(PLDHashTable* aTable, - const PLDHashEntryHdr* aEntry, - const void* aKey); +bool +PL_DHashMatchStringKey(PLDHashTable* aTable, + const PLDHashEntryHdr* aEntry, + const void* aKey); void PL_DHashMoveEntryStub(PLDHashTable* aTable, const PLDHashEntryHdr* aFrom, PLDHashEntryHdr* aTo); -void PL_DHashClearEntryStub(PLDHashTable* aTable, PLDHashEntryHdr* aEntry); +void +PL_DHashClearEntryStub(PLDHashTable* aTable, PLDHashEntryHdr* aEntry); -/* - * If you use PLDHashEntryStub or a subclass of it as your entry struct, and - * if your entries move via memcpy and clear via memset(0), you can use these - * stub operations. - */ -const PLDHashTableOps* PL_DHashGetStubOps(void); +// If you use PLDHashEntryStub or a subclass of it as your entry struct, and +// if your entries move via memcpy and clear via memset(0), you can use these +// stub operations. +const PLDHashTableOps* +PL_DHashGetStubOps(void); + +// The following function are deprecated. Use the equivalent class methods +// instead: PLDHashTable::Search() instead of PL_DHashTableSearch(), etc. -/* - * To search for a key in |table|, call: - * - * entry = PL_DHashTableSearch(table, key); - * - * If |entry| is non-null, |key| was found. If |entry| is null, key was not - * found. - */ PLDHashEntryHdr* PL_DHASH_FASTCALL PL_DHashTableSearch(PLDHashTable* aTable, const void* aKey); -/* - * To add an entry identified by key to table, call: - * - * entry = PL_DHashTableAdd(table, key, mozilla::fallible); - * - * If entry is null upon return, then the table is severely overloaded and - * memory can't be allocated for entry storage. - * - * Otherwise, aEntry->mKeyHash has been set so that - * PLDHashTable::EntryIsFree(entry) is false, and it is up to the caller to - * initialize the key and value parts of the entry sub-type, if they have not - * been set already (i.e. if entry was not already in the table, and if the - * optional initEntry hook was not used). - */ PLDHashEntryHdr* PL_DHASH_FASTCALL PL_DHashTableAdd(PLDHashTable* aTable, const void* aKey, const mozilla::fallible_t&); -/* - * This is like the other PL_DHashTableAdd() function, but infallible, and so - * never returns null. - */ PLDHashEntryHdr* PL_DHASH_FASTCALL PL_DHashTableAdd(PLDHashTable* aTable, const void* aKey); -/* - * To remove an entry identified by key from table, call: - * - * PL_DHashTableRemove(table, key); - * - * If key's entry is found, it is cleared (via table->mOps->clearEntry). - */ void PL_DHASH_FASTCALL PL_DHashTableRemove(PLDHashTable* aTable, const void* aKey); -/* - * Remove an entry already accessed via PL_DHashTableSearch or PL_DHashTableAdd. - * - * NB: this is a "raw" or low-level routine, intended to be used only where - * the inefficiency of a full PL_DHashTableRemove (which rehashes in order - * to find the entry given its key) is not tolerable. This function does not - * shrink the table if it is underloaded. - */ -void PL_DHashTableRawRemove(PLDHashTable* aTable, PLDHashEntryHdr* aEntry); +void +PL_DHashTableRawRemove(PLDHashTable* aTable, PLDHashEntryHdr* aEntry); -/** - * Measure the size of the table's entry storage, and if - * |aSizeOfEntryExcludingThis| is non-nullptr, measure the size of things - * pointed to by entries. Doesn't measure |mOps| because it's often shared - * between tables. - */ -size_t PL_DHashTableSizeOfExcludingThis( +size_t +PL_DHashTableSizeOfExcludingThis( const PLDHashTable* aTable, PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis, mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr); -/** - * Like PL_DHashTableSizeOfExcludingThis, but includes sizeof(*this). - */ -size_t PL_DHashTableSizeOfIncludingThis( +size_t +PL_DHashTableSizeOfIncludingThis( const PLDHashTable* aTable, PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis, mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr); #ifdef DEBUG -/** - * Mark a table as immutable for the remainder of its lifetime. This - * changes the implementation from ASSERTing one set of invariants to - * ASSERTing a different set. - * - * When a table is NOT marked as immutable, the table implementation - * asserts that the table is not mutated from its own callbacks. It - * assumes the caller protects the table from being accessed on multiple - * threads simultaneously. - * - * When the table is marked as immutable, the re-entry assertions will - * no longer trigger erroneously due to multi-threaded access. Instead, - * mutations will cause assertions. - */ -void PL_DHashMarkTableImmutable(PLDHashTable* aTable); +void +PL_DHashMarkTableImmutable(PLDHashTable* aTable); #endif #endif /* pldhash_h___ */ diff --git a/xpcom/string/nsTString.h b/xpcom/string/nsTString.h index 757fda7689d..93f39d20ccb 100644 --- a/xpcom/string/nsTString.h +++ b/xpcom/string/nsTString.h @@ -560,7 +560,7 @@ protected: * nsAutoString for wide characters * nsAutoCString for narrow characters */ -class nsTAutoString_CharT : public nsTFixedString_CharT +class MOZ_NON_MEMMOVABLE nsTAutoString_CharT : public nsTFixedString_CharT { public: