Bug 1525245 - Stabilize cookiePolicy/cookiePermission for live documents - part 11 - windows/workers/documents must keep the current cookie settings and ignore changes, r=Ehsan
authorAndrea Marchesini <amarchesini@mozilla.com>
Fri, 08 Mar 2019 09:03:38 +0000
changeset 463125 c11d3680e3d184c2404ad8a48d166bd8fe19f4df
parent 463124 98ff0248c6079b9518e2b96d19bacb5402a21bda
child 463126 8821567e070ffa8d5140db8135003b20e8128cd0
push id80001
push useramarchesini@mozilla.com
push dateFri, 08 Mar 2019 09:38:56 +0000
treeherderautoland@3cddc7cd4da5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersEhsan
bugs1525245
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1525245 - Stabilize cookiePolicy/cookiePermission for live documents - part 11 - windows/workers/documents must keep the current cookie settings and ignore changes, r=Ehsan Differential Revision: https://phabricator.services.mozilla.com/D18960
dom/base/Document.cpp
dom/base/nsGlobalWindowOuter.cpp
dom/workers/RuntimeService.cpp
netwerk/cookie/test/browser/browser_broadcastChannel.js
netwerk/cookie/test/browser/browser_domCache.js
netwerk/cookie/test/browser/browser_indexedDB.js
netwerk/cookie/test/browser/browser_serviceWorker.js
netwerk/cookie/test/browser/browser_sharedWorker.js
netwerk/cookie/test/browser/browser_storage.js
netwerk/cookie/test/browser/head.js
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -11800,17 +11800,17 @@ void Document::SetDocTreeHadPlayRevoked(
   }
 }
 
 DocumentAutoplayPolicy Document::AutoplayPolicy() const {
   return AutoplayPolicy::IsAllowedToPlay(*this);
 }
 
 void Document::MaybeAllowStorageForOpenerAfterUserInteraction() {
-  if (StaticPrefs::network_cookie_cookieBehavior() !=
+  if (mCookieSettings->GetCookieBehavior() !=
       nsICookieService::BEHAVIOR_REJECT_TRACKER) {
     return;
   }
 
   // This will probably change for project fission, but currently this document
   // and the opener are on the same process. In the future, we should make this
   // part async.
 
@@ -12316,18 +12316,18 @@ already_AddRefed<mozilla::dom::Promise> 
 
   // Step 2. If the document has a null origin, reject.
   if (NodePrincipal()->GetIsNullPrincipal()) {
     promise->MaybeRejectWithUndefined();
     return promise.forget();
   }
 
   // Only enforce third-party checks when there is a reason to enforce them.
-  if (StaticPrefs::network_cookie_cookieBehavior() !=
-      nsICookieService::BEHAVIOR_ACCEPT) {
+  if (mCookieSettings->GetCookieBehavior() !=
+      nsICookieService::BEHAVIOR_REJECT_TRACKER) {
     // Step 3. If the document's frame is the main frame, resolve.
     if (IsTopLevelContentDocument()) {
       promise->MaybeResolveWithUndefined();
       return promise.forget();
     }
 
     // Step 4. If the sub frame's origin is equal to the main frame's, resolve.
     nsCOMPtr<Document> topLevelDoc = GetTopLevelContentDocument();
@@ -12369,17 +12369,17 @@ already_AddRefed<mozilla::dom::Promise> 
 
   if (nsContentUtils::IsInPrivateBrowsing(this)) {
     // If the document is in PB mode, it doesn't have access to its persistent
     // cookie jar, so reject the promise here.
     promise->MaybeRejectWithUndefined();
     return promise.forget();
   }
 
-  if (StaticPrefs::network_cookie_cookieBehavior() ==
+  if (mCookieSettings->GetCookieBehavior() ==
           nsICookieService::BEHAVIOR_REJECT_TRACKER &&
       inner) {
     // Only do something special for third-party tracking content.
     if (nsContentUtils::StorageDisabledByAntiTracking(this, nullptr)) {
       // Note: If this has returned true, the top-level document is guaranteed
       // to not be on the Content Blocking allow list.
       DebugOnly<bool> isOnAllowList = false;
       // If we have a parent document, it has to be non-private since we
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -1253,20 +1253,16 @@ nsGlobalWindowOuter::~nsGlobalWindowOute
 
   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
   if (ac) ac->RemoveWindowAsListener(this);
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->RemoveObserver(this, PERM_CHANGE_NOTIFICATION);
   }
-  nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
-  if (prefBranch) {
-    prefBranch->RemoveObserver("network.cookie.cookieBehavior", this);
-  }
 
   nsLayoutStatics::Release();
 }
 
 // static
 void nsGlobalWindowOuter::ShutDown() {
   AssertIsOnMainThread();
 
@@ -2290,30 +2286,28 @@ nsresult nsGlobalWindowOuter::SetNewDocu
 
   // If we have a recorded interesting Large-Allocation header status, report it
   // to the newly attached document.
   ReportLargeAllocStatus();
   mLargeAllocStatus = LargeAllocStatus::NONE;
 
   mHasStorageAccess = false;
   nsIURI* uri = aDocument->GetDocumentURI();
-  if (newInnerWindow) {
-    if (StaticPrefs::network_cookie_cookieBehavior() ==
-            nsICookieService::BEHAVIOR_REJECT_TRACKER &&
-        nsContentUtils::IsThirdPartyWindowOrChannel(newInnerWindow, nullptr,
-                                                    uri) &&
-        nsContentUtils::IsTrackingResourceWindow(newInnerWindow)) {
-      // Grant storage access by default if the first-party storage access
-      // permission has been granted already.
-      // Don't notify in this case, since we would be notifying the user
-      // needlessly.
-      mHasStorageAccess =
-          AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
-              newInnerWindow, uri, nullptr);
-    }
+  if (newInnerWindow &&
+      aDocument->CookieSettings()->GetCookieBehavior() ==
+          nsICookieService::BEHAVIOR_REJECT_TRACKER &&
+      nsContentUtils::IsThirdPartyWindowOrChannel(newInnerWindow, nullptr,
+                                                  uri) &&
+      nsContentUtils::IsTrackingResourceWindow(newInnerWindow)) {
+    // Grant storage access by default if the first-party storage access
+    // permission has been granted already.
+    // Don't notify in this case, since we would be notifying the user
+    // needlessly.
+    mHasStorageAccess = AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
+        newInnerWindow, uri, nullptr);
   }
 
   return NS_OK;
 }
 
 void nsGlobalWindowOuter::PreloadLocalStorage() {
   if (!Storage::StoragePrefIsEnabled()) {
     return;
@@ -6943,21 +6937,16 @@ nsGlobalWindowOuter::GetInterface(const 
 //*****************************************************************************
 // nsGlobalWindowOuter::nsIObserver
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsGlobalWindowOuter::Observe(nsISupports* aSupports, const char* aTopic,
                              const char16_t* aData) {
   if (!nsCRT::strcmp(aTopic, PERM_CHANGE_NOTIFICATION)) {
-    if (!nsCRT::strcmp(aData, u"cleared") && !aSupports) {
-      // All permissions have been cleared.
-      mHasStorageAccess = false;
-      return NS_OK;
-    }
     nsCOMPtr<nsIPermission> permission = do_QueryInterface(aSupports);
     if (!permission) {
       return NS_OK;
     }
     nsIPrincipal* principal = GetPrincipal();
     if (!principal) {
       return NS_OK;
     }
@@ -6979,20 +6968,16 @@ nsGlobalWindowOuter::Observe(nsISupports
            expireTime >= PR_Now() / 1000) ||
           (expireType == nsIPermissionManager::EXPIRE_SESSION &&
            expireTime != 0)) {
         // Permission hasn't expired yet.
         mHasStorageAccess = true;
         return NS_OK;
       }
     }
-  } else if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
-    // Reset the storage access permission when our cookie policy changes.
-    mHasStorageAccess = false;
-    return NS_OK;
   }
   return NS_OK;
 }
 
 bool nsGlobalWindowOuter::IsSuspended() const {
   MOZ_ASSERT(NS_IsMainThread());
   // No inner means we are effectively suspended
   if (!mInnerWindow) {
@@ -7780,20 +7765,16 @@ already_AddRefed<nsGlobalWindowOuter> ns
   if (obs) {
     // Delay calling AddObserver until we hit the event loop, in case we may be
     // in the middle of modifying the observer list somehow.
     NS_DispatchToMainThread(
         NS_NewRunnableFunction("PermChangeDelayRunnable", [obs, window] {
           obs->AddObserver(window, PERM_CHANGE_NOTIFICATION, true);
         }));
   }
-  nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
-  if (prefBranch) {
-    prefBranch->AddObserver("network.cookie.cookieBehavior", window, true);
-  }
   return window.forget();
 }
 
 nsIURI* nsPIDOMWindowOuter::GetDocumentURI() const {
   return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
 }
 
 void nsPIDOMWindowOuter::MaybeCreateDoc() {
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -2014,18 +2014,20 @@ void RuntimeService::ResumeWorkersForWin
     workers[index]->ParentWindowResumed();
   }
 }
 
 void RuntimeService::PropagateFirstPartyStorageAccessGranted(
     nsPIDOMWindowInner* aWindow) {
   AssertIsOnMainThread();
   MOZ_ASSERT(aWindow);
-  MOZ_ASSERT(StaticPrefs::network_cookie_cookieBehavior() ==
-             nsICookieService::BEHAVIOR_REJECT_TRACKER);
+  MOZ_ASSERT_IF(
+      aWindow->GetExtantDoc(),
+      aWindow->GetExtantDoc()->CookieSettings()->GetCookieBehavior() ==
+          nsICookieService::BEHAVIOR_REJECT_TRACKER);
 
   nsTArray<WorkerPrivate*> workers;
   GetWorkersForWindow(aWindow, workers);
 
   for (uint32_t index = 0; index < workers.Length(); index++) {
     workers[index]->PropagateFirstPartyStorageAccessGranted();
   }
 }
@@ -2396,18 +2398,20 @@ void ResumeWorkersForWindow(nsPIDOMWindo
   if (runtime) {
     runtime->ResumeWorkersForWindow(aWindow);
   }
 }
 
 void PropagateFirstPartyStorageAccessGrantedToWorkers(
     nsPIDOMWindowInner* aWindow) {
   AssertIsOnMainThread();
-  MOZ_ASSERT(StaticPrefs::network_cookie_cookieBehavior() ==
-             nsICookieService::BEHAVIOR_REJECT_TRACKER);
+  MOZ_ASSERT_IF(
+      aWindow->GetExtantDoc(),
+      aWindow->GetExtantDoc()->CookieSettings()->GetCookieBehavior() ==
+          nsICookieService::BEHAVIOR_REJECT_TRACKER);
 
   RuntimeService* runtime = RuntimeService::GetService();
   if (runtime) {
     runtime->PropagateFirstPartyStorageAccessGranted(aWindow);
   }
 }
 
 WorkerPrivate* GetWorkerPrivateFromContext(JSContext* aCx) {
--- a/netwerk/cookie/test/browser/browser_broadcastChannel.js
+++ b/netwerk/cookie/test/browser/browser_broadcastChannel.js
@@ -1,75 +1,75 @@
 // BroadcastChannel is not considered part of CookieJar. It's not allowed to
 // communicate with other windows with different cookie settings.
 
 CookiePolicyHelper.runTest("BroadcastChannel", {
-  cookieJarAccessAllowed: async _ => {
-    new content.BroadcastChannel("hello");
+  cookieJarAccessAllowed: async w => {
+    new w.BroadcastChannel("hello");
     ok(true, "BroadcastChannel be used");
   },
 
-  cookieJarAccessDenied: async _ => {
+  cookieJarAccessDenied: async w => {
     try {
-      new content.BroadcastChannel("hello");
+      new w.BroadcastChannel("hello");
       ok(false, "BroadcastChannel cannot be used!");
     } catch (e) {
       ok(true, "BroadcastChannel cannot be used!");
       is(e.name, "SecurityError", "We want a security error message.");
     }
   }
 });
 
 CookiePolicyHelper.runTest("BroadcastChannel in workers", {
-  cookieJarAccessAllowed: async _ => {
+  cookieJarAccessAllowed: async w => {
     function nonBlockingCode() {
       new BroadcastChannel("hello");
       postMessage(true);
     }
 
-    let blob = new content.Blob([nonBlockingCode.toString() + "; nonBlockingCode();"]);
+    let blob = new w.Blob([nonBlockingCode.toString() + "; nonBlockingCode();"]);
     ok(blob, "Blob has been created");
 
-    let blobURL = content.URL.createObjectURL(blob);
+    let blobURL = w.URL.createObjectURL(blob);
     ok(blobURL, "Blob URL has been created");
 
-    let worker = new content.Worker(blobURL);
+    let worker = new w.Worker(blobURL);
     ok(worker, "Worker has been created");
 
-    await new content.Promise((resolve, reject) => {
+    await new w.Promise((resolve, reject) => {
       worker.onmessage = function(e) {
         if (e) {
           resolve();
         } else {
           reject();
         }
       };
     });
   },
 
-  cookieJarAccessDenied: async _ => {
+  cookieJarAccessDenied: async w => {
     function blockingCode() {
       try {
         new BroadcastChannel("hello");
         postMessage(false);
       } catch (e) {
         postMessage(e.name == "SecurityError");
       }
     }
 
-    let blob = new content.Blob([blockingCode.toString() + "; blockingCode();"]);
+    let blob = new w.Blob([blockingCode.toString() + "; blockingCode();"]);
     ok(blob, "Blob has been created");
 
-    let blobURL = content.URL.createObjectURL(blob);
+    let blobURL = w.URL.createObjectURL(blob);
     ok(blobURL, "Blob URL has been created");
 
-    let worker = new content.Worker(blobURL);
+    let worker = new w.Worker(blobURL);
     ok(worker, "Worker has been created");
 
-    await new content.Promise((resolve, reject) => {
+    await new w.Promise((resolve, reject) => {
       worker.onmessage = function(e) {
         if (e) {
           resolve();
         } else {
           reject();
         }
       };
     });
--- a/netwerk/cookie/test/browser/browser_domCache.js
+++ b/netwerk/cookie/test/browser/browser_domCache.js
@@ -1,13 +1,13 @@
 CookiePolicyHelper.runTest("DOM Cache", {
-  cookieJarAccessAllowed: async _ => {
-    await content.caches.open("wow").then(
+  cookieJarAccessAllowed: async w => {
+    await w.caches.open("wow").then(
       _ => { ok(true, "DOM Cache can be used!"); },
       _ => { ok(false, "DOM Cache can be used!"); });
   },
 
-  cookieJarAccessDenied: async _ => {
-    await content.caches.open("wow").then(
+  cookieJarAccessDenied: async w => {
+    await w.caches.open("wow").then(
       _ => { ok(false, "DOM Cache cannot be used!"); },
       _ => { ok(true, "DOM Cache cannot be used!"); });
   },
 });
--- a/netwerk/cookie/test/browser/browser_indexedDB.js
+++ b/netwerk/cookie/test/browser/browser_indexedDB.js
@@ -1,76 +1,76 @@
 CookiePolicyHelper.runTest("IndexedDB", {
-  cookieJarAccessAllowed: async _ => {
-    content.indexedDB.open("test", "1");
+  cookieJarAccessAllowed: async w => {
+    w.indexedDB.open("test", "1");
     ok(true, "IDB should be allowed");
   },
 
-  cookieJarAccessDenied: async _ => {
+  cookieJarAccessDenied: async w => {
     try {
-      content.indexedDB.open("test", "1");
+      w.indexedDB.open("test", "1");
       ok(false, "IDB should be blocked");
     } catch (e) {
       ok(true, "IDB should be blocked");
       is(e.name, "SecurityError", "We want a security error message.");
     }
   },
 });
 
 CookiePolicyHelper.runTest("IndexedDB in workers", {
-  cookieJarAccessAllowed: async _ => {
+  cookieJarAccessAllowed: async w => {
     function nonBlockCode() {
       indexedDB.open("test", "1");
       postMessage(true);
     }
 
-    let blob = new content.Blob([nonBlockCode.toString() + "; nonBlockCode();"]);
+    let blob = new w.Blob([nonBlockCode.toString() + "; nonBlockCode();"]);
     ok(blob, "Blob has been created");
 
-    let blobURL = content.URL.createObjectURL(blob);
+    let blobURL = w.URL.createObjectURL(blob);
     ok(blobURL, "Blob URL has been created");
 
-    let worker = new content.Worker(blobURL);
+    let worker = new w.Worker(blobURL);
     ok(worker, "Worker has been created");
 
-    await new content.Promise((resolve, reject) => {
+    await new w.Promise((resolve, reject) => {
       worker.onmessage = function(e) {
         if (e.data) {
           resolve();
         } else {
           reject();
         }
       };
 
       worker.onerror = function(e) {
         reject();
       };
     });
   },
 
-  cookieJarAccessDenied: async _ => {
+  cookieJarAccessDenied: async w => {
     function blockCode() {
       try {
         indexedDB.open("test", "1");
         postMessage(false);
       } catch (e) {
         postMessage(e.name == "SecurityError");
       }
     }
 
-    let blob = new content.Blob([blockCode.toString() + "; blockCode();"]);
+    let blob = new w.Blob([blockCode.toString() + "; blockCode();"]);
     ok(blob, "Blob has been created");
 
-    let blobURL = content.URL.createObjectURL(blob);
+    let blobURL = w.URL.createObjectURL(blob);
     ok(blobURL, "Blob URL has been created");
 
-    let worker = new content.Worker(blobURL);
+    let worker = new w.Worker(blobURL);
     ok(worker, "Worker has been created");
 
-    await new content.Promise((resolve, reject) => {
+    await new w.Promise((resolve, reject) => {
       worker.onmessage = function(e) {
         if (e.data) {
           resolve();
         } else {
           reject();
         }
       };
 
--- a/netwerk/cookie/test/browser/browser_serviceWorker.js
+++ b/netwerk/cookie/test/browser/browser_serviceWorker.js
@@ -1,24 +1,24 @@
 CookiePolicyHelper.runTest("ServiceWorker", {
   prefs: [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
     ["dom.ipc.processCount", 1],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
   ],
 
-  cookieJarAccessAllowed: async _ => {
-    await content.navigator.serviceWorker.register("file_empty.js").then(
+  cookieJarAccessAllowed: async w => {
+    await w.navigator.serviceWorker.register("file_empty.js").then(
       reg => { ok(true, "ServiceWorker can be used!"); return reg; },
       _ => { ok(false, "ServiceWorker cannot be used! " + _); }).then(
       reg => reg.unregister(),
       _ => { ok(false, "unregister failed"); }).
       catch(e => ok(false, "Promise rejected: " + e));
   },
 
-  cookieJarAccessDenied: async _ => {
-    await content.navigator.serviceWorker.register("file_empty.js").then(
+  cookieJarAccessDenied: async w => {
+    await w.navigator.serviceWorker.register("file_empty.js").then(
       _ => { ok(false, "ServiceWorker cannot be used!"); },
       _ => { ok(true, "ServiceWorker cannot be used!"); }).
       catch(e => ok(false, "Promise rejected: " + e));
   },
 });
--- a/netwerk/cookie/test/browser/browser_sharedWorker.js
+++ b/netwerk/cookie/test/browser/browser_sharedWorker.js
@@ -1,16 +1,16 @@
 CookiePolicyHelper.runTest("SharedWorker", {
-  cookieJarAccessAllowed: async _ => {
-    new content.SharedWorker("a.js", "foo");
+  cookieJarAccessAllowed: async w => {
+    new w.SharedWorker("a.js", "foo");
     ok(true, "SharedWorker is allowed");
   },
 
-  cookieJarAccessDenied: async _ => {
+  cookieJarAccessDenied: async w => {
     try {
-      new content.SharedWorker("a.js", "foo");
+      new w.SharedWorker("a.js", "foo");
       ok(false, "SharedWorker cannot be used!");
     } catch (e) {
       ok(true, "SharedWorker cannot be used!");
       is(e.name, "SecurityError", "We want a security error message.");
     }
   },
 });
--- a/netwerk/cookie/test/browser/browser_storage.js
+++ b/netwerk/cookie/test/browser/browser_storage.js
@@ -1,41 +1,41 @@
 CookiePolicyHelper.runTest("SessionStorage", {
-  cookieJarAccessAllowed: async _ => {
+  cookieJarAccessAllowed: async w => {
     try {
-      content.sessionStorage.foo = 42;
+      w.sessionStorage.foo = 42;
       ok(true, "SessionStorage works");
     } catch (e) {
       ok(false, "SessionStorage works");
     }
   },
 
-  cookieJarAccessDenied: async _ => {
+  cookieJarAccessDenied: async w => {
     try {
-      content.sessionStorage.foo = 42;
+      w.sessionStorage.foo = 42;
       ok(false, "SessionStorage doesn't work");
     } catch (e) {
       ok(true, "SessionStorage doesn't work");
       is(e.name, "SecurityError", "We want a security error message.");
     }
   },
 });
 
 CookiePolicyHelper.runTest("LocalStorage", {
-  cookieJarAccessAllowed: async _ => {
+  cookieJarAccessAllowed: async w => {
     try {
-      content.localStorage.foo = 42;
+      w.localStorage.foo = 42;
       ok(true, "LocalStorage works");
     } catch (e) {
       ok(false, "LocalStorage works");
     }
   },
 
-  cookieJarAccessDenied: async _ => {
+  cookieJarAccessDenied: async w => {
     try {
-      content.localStorage.foo = 42;
+      w.localStorage.foo = 42;
       ok(false, "LocalStorage doesn't work");
     } catch (e) {
       ok(true, "LocalStorage doesn't work");
-      is(e.name, "SecurityError", "We want a security error message.");
+      is(e.name, "TypeError", "We want a security error message.");
     }
   },
 });
--- a/netwerk/cookie/test/browser/head.js
+++ b/netwerk/cookie/test/browser/head.js
@@ -92,40 +92,58 @@ this.CookiePolicyHelper = {
 
       // Let's open a tab and load content.
       let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
       gBrowser.selectedTab = tab;
 
       let browser = gBrowser.getBrowserForTab(tab);
       await BrowserTestUtils.browserLoaded(browser);
 
+      // Let's create an iframe.
+      await ContentTask.spawn(browser, { url: TEST_TOP_PAGE },
+                              async obj => {
+        return new content.Promise(resolve => {
+          let ifr = content.document.createElement('iframe');
+          ifr.setAttribute("id", "iframe");
+          ifr.src = obj.url;
+          ifr.onload = resolve;
+          content.document.body.appendChild(ifr);
+        });
+      });
+
       // Let's exec the "good" callback.
       info("Executing the test after setting the cookie behavior to " + config.fromBehavior + " and permission to " + config.fromPermission);
       await ContentTask.spawn(browser,
                               { callback: goodCb.toString() },
                               async obj => {
         let runnableStr = `(() => {return (${obj.callback});})();`;
         let runnable = eval(runnableStr); // eslint-disable-line no-eval
-        await runnable();
+        await runnable(content);
+
+        let ifr = content.document.getElementById("iframe");
+        await runnable(ifr.contentWindow);
       });
 
       // Now, let's change the cookie settings
       Services.perms.add(uri, "cookie", config.toPermission);
       await SpecialPowers.pushPrefEnv({"set": [
         ["network.cookie.cookieBehavior", config.toBehavior],
       ]});
 
       // We still want the good callback to succeed.
       info("Executing the test after setting the cookie behavior to " + config.toBehavior + " and permission to " + config.toPermission);
       await ContentTask.spawn(browser,
                               { callback: goodCb.toString() },
                               async obj => {
         let runnableStr = `(() => {return (${obj.callback});})();`;
         let runnable = eval(runnableStr); // eslint-disable-line no-eval
-        await runnable.call(content.window);
+        await runnable(content);
+
+        let ifr = content.document.getElementById("iframe");
+        await runnable(ifr.contentWindow);
       });
 
       // Let's close the tab.
       BrowserTestUtils.removeTab(tab);
 
       // Let's open a new tab and load content again.
       tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
       gBrowser.selectedTab = tab;
@@ -135,17 +153,17 @@ this.CookiePolicyHelper = {
 
       // Let's exec the "bad" callback.
       info("Executing the test in a new tab");
       await ContentTask.spawn(browser,
                               { callback: badCb.toString() },
                               async obj => {
         let runnableStr = `(() => {return (${obj.callback});})();`;
         let runnable = eval(runnableStr); // eslint-disable-line no-eval
-        await runnable.call(content.window);
+        await runnable(content);
       });
 
       // Let's close the tab.
       BrowserTestUtils.removeTab(tab);
 
       // Cleanup.
       await new Promise(resolve => {
         Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, resolve);