Bug 1344170: set firstPartyDomai on blob: URI. r=smaug
authorYoshi Huang <allstars.chh@mozilla.com>
Wed, 12 Apr 2017 14:47:48 +0800
changeset 402718 89407b3607a2feedd46b2d13717724bc5f41b33b
parent 402717 9f2fe5e3f78c8174fab116ebc9091d0e357fb121
child 402719 288f9c879d41b61c90f16af0e002d6331df921bd
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1344170
milestone55.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 1344170: set firstPartyDomai on blob: URI. r=smaug A web page could generate an URL by URl.createObjectURL(new Blob(...)); then navigate to this generated URL. In this case the (top-level) document URI will be blob:{origin}:{uuid}. And we try to add firstPartyDomain on this top-level document with blob URI, so the following request from this document could have correct origin attributes.
browser/components/originattributes/test/browser/browser.ini
browser/components/originattributes/test/browser/browser_firstPartyIsolation.js
browser/components/originattributes/test/browser/browser_firstPartyIsolation_blobURI.js
caps/OriginAttributes.cpp
--- a/browser/components/originattributes/test/browser/browser.ini
+++ b/browser/components/originattributes/test/browser/browser.ini
@@ -60,16 +60,17 @@ support-files =
 
 [browser_broadcastChannel.js]
 [browser_cache.js]
 [browser_cookieIsolation.js]
 [browser_favicon_firstParty.js]
 [browser_favicon_userContextId.js]
 [browser_firstPartyIsolation.js]
 [browser_firstPartyIsolation_aboutPages.js]
+[browser_firstPartyIsolation_blobURI.js]
 [browser_firstPartyIsolation_js_uri.js]
 [browser_localStorageIsolation.js]
 [browser_blobURLIsolation.js]
 [browser_imageCacheIsolation.js]
 [browser_sharedworker.js]
 [browser_httpauth.js]
 [browser_clientAuth.js]
 [browser_cacheAPI.js]
--- a/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js
+++ b/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js
@@ -1,15 +1,16 @@
 const BASE_URL = "http://mochi.test:8888/browser/browser/components/originattributes/test/browser/";
 const BASE_DOMAIN = "mochi.test";
 
 add_task(function* setup() {
   Services.prefs.setBoolPref("privacy.firstparty.isolate", true);
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref("privacy.firstparty.isolate");
+    Services.cookies.removeAll();
   });
 });
 
 /**
  * Test for the top-level document and child iframes should have the
  * firstPartyDomain attribute.
  */
 add_task(function* principal_test() {
new file mode 100644
--- /dev/null
+++ b/browser/components/originattributes/test/browser/browser_firstPartyIsolation_blobURI.js
@@ -0,0 +1,76 @@
+add_task(function* setup() {
+  Services.prefs.setBoolPref("privacy.firstparty.isolate", true);
+
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("privacy.firstparty.isolate");
+    Services.cookies.removeAll();
+  });
+});
+
+/**
+ * First we generate a Blob URI by using URL.createObjectURL(new Blob(..));
+ * then we navigate to this Blob URI, hence to make the top-level document URI
+ * is Blob URI.
+ * Later we create an iframe on this Blob: document, and we test that the iframe
+ * has correct firstPartyDomain.
+ */
+add_task(function* test_blob_uri_inherit_oa_from_content() {
+  const BASE_URI = "http://mochi.test:8888/browser/browser/components/" +
+                   "originattributes/test/browser/dummy.html";
+  const BASE_DOMAIN = "mochi.test";
+
+  // First we load a normal web page.
+  let win = yield BrowserTestUtils.openNewBrowserWindow({ remote: true });
+  let browser = win.gBrowser.selectedBrowser;
+  browser.loadURI(BASE_URI);
+  yield BrowserTestUtils.browserLoaded(browser);
+
+  // Then navigate to the blob: URI.
+  yield ContentTask.spawn(browser, { firstPartyDomain: BASE_DOMAIN }, function* (attrs) {
+    info("origin " + content.document.nodePrincipal.origin);
+    Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
+                 attrs.firstPartyDomain, "The document should have firstPartyDomain");
+
+    // Now we use createObjectURL to generate a blob URI and navigate to it.
+    let url = content.window.URL.createObjectURL(new content.window.Blob([
+      `<script src="http://mochi.test:8888/browser/browser/components/originattributes/test/browser/test.js"></script>`],
+      {"type": "text/html"}));
+    content.document.location = url;
+  });
+
+  // Wait for the Blob: URI to be loaded.
+  yield BrowserTestUtils.browserLoaded(browser, false, function(url) {
+    info("BrowserTestUtils.browserLoaded url=" + url);
+    return url.startsWith("blob:http://mochi.test:8888/");
+  });
+
+  // We verify the blob document has correct origin attributes.
+  // Then we inject an iframe to it.
+  yield ContentTask.spawn(browser, { firstPartyDomain: BASE_DOMAIN }, function* (attrs) {
+    Assert.ok(content.document.documentURI.startsWith("blob:http://mochi.test:8888/"),
+              "the document URI should be a blob URI.");
+    info("origin " + content.document.nodePrincipal.origin);
+    Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
+                 attrs.firstPartyDomain, "The document should have firstPartyDomain");
+
+    let iframe = content.document.createElement("iframe");
+    iframe.src = "http://example.com";
+    iframe.id = "iframe1";
+    content.document.body.appendChild(iframe);
+  });
+
+  // Wait for the iframe to be loaded.
+//  yield BrowserTestUtils.browserLoaded(browser, true, function(url) {
+//    info("BrowserTestUtils.browserLoaded iframe url=" + url);
+//    return url == "http://example.com/";
+//  });
+
+  // Finally we verify the iframe has correct origin attributes.
+  yield ContentTask.spawn(browser, { firstPartyDomain: BASE_DOMAIN }, function* (attrs) {
+    let iframe = content.document.getElementById("iframe1");
+    Assert.equal(iframe.contentDocument.nodePrincipal.originAttributes.firstPartyDomain,
+                 attrs.firstPartyDomain, "iframe should inherit firstPartyDomain from blob: URI");
+  });
+
+  win.close();
+});
--- a/caps/OriginAttributes.cpp
+++ b/caps/OriginAttributes.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/OriginAttributes.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/URLSearchParams.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "nsIEffectiveTLDService.h"
 #include "nsIURI.h"
+#include "nsIURIWithPrincipal.h"
 
 namespace mozilla {
 
 using dom::URLParams;
 
 bool OriginAttributes::sFirstPartyIsolation = false;
 bool OriginAttributes::sRestrictedOpenerAccess = false;
 
@@ -47,26 +48,39 @@ OriginAttributes::SetFirstPartyDomain(co
     do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
   MOZ_ASSERT(tldService);
   if (!tldService) {
     return;
   }
 
   nsAutoCString baseDomain;
   nsresult rv = tldService->GetBaseDomain(aURI, 0, baseDomain);
-  if (NS_FAILED(rv)) {
-    nsAutoCString scheme;
-    rv = aURI->GetScheme(scheme);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    if (scheme.EqualsLiteral("about")) {
-      baseDomain.AssignLiteral(ABOUT_URI_FIRST_PARTY_DOMAIN);
+  if (NS_SUCCEEDED(rv)) {
+    mFirstPartyDomain = NS_ConvertUTF8toUTF16(baseDomain);
+    return;
+  }
+
+  nsAutoCString scheme;
+  rv = aURI->GetScheme(scheme);
+  NS_ENSURE_SUCCESS_VOID(rv);
+  if (scheme.EqualsLiteral("about")) {
+    mFirstPartyDomain.AssignLiteral(ABOUT_URI_FIRST_PARTY_DOMAIN);
+  } else if (scheme.EqualsLiteral("blob")) {
+    nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
+    if (uriPrinc) {
+      nsCOMPtr<nsIPrincipal> principal;
+      rv = uriPrinc->GetPrincipal(getter_AddRefs(principal));
+      NS_ENSURE_SUCCESS_VOID(rv);
+
+      MOZ_ASSERT(principal, "blob URI but no principal.");
+      if (principal) {
+        mFirstPartyDomain = principal->OriginAttributesRef().mFirstPartyDomain;
+      }
     }
   }
-
-  mFirstPartyDomain = NS_ConvertUTF8toUTF16(baseDomain);
 }
 
 void
 OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument,
                                       const nsACString& aDomain)
 {
   bool isFirstPartyEnabled = IsFirstPartyEnabled();