diff --git a/browser/components/originattributes/test/browser/browser.ini b/browser/components/originattributes/test/browser/browser.ini index fb56e877af95..1093c841c21e 100644 --- a/browser/components/originattributes/test/browser/browser.ini +++ b/browser/components/originattributes/test/browser/browser.ini @@ -65,6 +65,7 @@ support-files = [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] diff --git a/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js b/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js index 1f2e82263003..3f9fce56eca7 100644 --- a/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js +++ b/browser/components/originattributes/test/browser/browser_firstPartyIsolation.js @@ -5,6 +5,7 @@ add_task(function* setup() { Services.prefs.setBoolPref("privacy.firstparty.isolate", true); registerCleanupFunction(function() { Services.prefs.clearUserPref("privacy.firstparty.isolate"); + Services.cookies.removeAll(); }); }); diff --git a/browser/components/originattributes/test/browser/browser_firstPartyIsolation_blobURI.js b/browser/components/originattributes/test/browser/browser_firstPartyIsolation_blobURI.js new file mode 100644 index 000000000000..79abc9067e93 --- /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([ + ``], + {"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(); +}); diff --git a/caps/OriginAttributes.cpp b/caps/OriginAttributes.cpp index 9ee38822e33a..93137d5dabf9 100644 --- a/caps/OriginAttributes.cpp +++ b/caps/OriginAttributes.cpp @@ -10,6 +10,7 @@ #include "mozilla/dom/quota/QuotaManager.h" #include "nsIEffectiveTLDService.h" #include "nsIURI.h" +#include "nsIURIWithPrincipal.h" namespace mozilla { @@ -52,16 +53,29 @@ OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument, 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; } - mFirstPartyDomain = NS_ConvertUTF8toUTF16(baseDomain); + 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 uriPrinc = do_QueryInterface(aURI); + if (uriPrinc) { + nsCOMPtr 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; + } + } + } } void