mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Backed out 5 changesets (bug 1260931)
Backed out changeset 86e1a437021b (bug 1260931) Backed out changeset be65e87da9e3 (bug 1260931) Backed out changeset 39cff1d988fd (bug 1260931) Backed out changeset 2fa7c4d8a5bc (bug 1260931) Backed out changeset 075d612841fb (bug 1260931)
This commit is contained in:
parent
7db44d87f4
commit
31c5f85098
@ -526,6 +526,8 @@ pref("privacy.sanitize.migrateFx3Prefs", false);
|
||||
|
||||
pref("privacy.panicButton.enabled", true);
|
||||
|
||||
pref("privacy.firstparty.isolate", false);
|
||||
|
||||
pref("network.proxy.share_proxy_settings", false); // use the same proxy settings for all protocols
|
||||
|
||||
// simple gestures support
|
||||
|
@ -2,12 +2,26 @@
|
||||
skip-if = buildapp == "mulet"
|
||||
tags = usercontextid firstpartyisolation originattributes
|
||||
support-files =
|
||||
dummy.html
|
||||
file_firstPartyBasic.html
|
||||
head.js
|
||||
test.js
|
||||
test.js^headers^
|
||||
test.html
|
||||
test2.html
|
||||
test2.js
|
||||
test2.js^headers^
|
||||
test_firstParty.html
|
||||
test_firstParty_cookie.html
|
||||
test_firstParty_html_redirect.html
|
||||
test_firstParty_http_redirect.html
|
||||
test_firstParty_http_redirect.html^headers^
|
||||
test_firstParty_iframe_http_redirect.html
|
||||
test_firstParty_postMessage.html
|
||||
window.html
|
||||
worker_blobify.js
|
||||
worker_deblobify.js
|
||||
|
||||
[browser_blobURLIsolation.js]
|
||||
[browser_dummy.js]
|
||||
skip-if = true
|
||||
[browser_firstPartyIsolation.js]
|
||||
[browser_localStorageIsolation.js]
|
||||
|
@ -0,0 +1,174 @@
|
||||
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");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Test for the top-level document and child iframes should have the
|
||||
* firstPartyDomain attribute.
|
||||
*/
|
||||
add_task(function* principal_test() {
|
||||
let tab = gBrowser.addTab(BASE_URL + "test_firstParty.html");
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser, true, function (url) {
|
||||
return url == BASE_URL + "test_firstParty.html";
|
||||
});
|
||||
|
||||
yield ContentTask.spawn(tab.linkedBrowser, { firstPartyDomain: BASE_DOMAIN }, function* (attrs) {
|
||||
info("document principal: " + content.document.nodePrincipal.origin);
|
||||
Assert.equal(docShell.getOriginAttributes().firstPartyDomain, "",
|
||||
"top-level docShell shouldn't have firstPartyDomain attribute.");
|
||||
Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
|
||||
attrs.firstPartyDomain, "The document should have firstPartyDomain");
|
||||
|
||||
for (let i = 1; i < 4; i++) {
|
||||
let iframe = content.document.getElementById("iframe" + i);
|
||||
info("iframe principal: " + iframe.contentDocument.nodePrincipal.origin);
|
||||
Assert.equal(iframe.frameLoader.docShell.getOriginAttributes().firstPartyDomain,
|
||||
attrs.firstPartyDomain, "iframe's docshell should have firstPartyDomain");
|
||||
Assert.equal(iframe.contentDocument.nodePrincipal.originAttributes.firstPartyDomain,
|
||||
attrs.firstPartyDomain, "iframe should have firstPartyDomain");
|
||||
}
|
||||
});
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
/**
|
||||
* Test for the cookie jars of the top-level document and child iframe should be
|
||||
* isolated by firstPartyDomain.
|
||||
*/
|
||||
add_task(function* cookie_test() {
|
||||
let tab = gBrowser.addTab(BASE_URL + "test_firstParty_cookie.html");
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser, true);
|
||||
|
||||
let iter = Services.cookies.enumerator;
|
||||
let count = 0;
|
||||
while (iter.hasMoreElements()) {
|
||||
count++;
|
||||
let cookie = iter.getNext().QueryInterface(Ci.nsICookie2);
|
||||
Assert.equal(cookie.value, "foo", "Cookie value should be foo");
|
||||
Assert.equal(cookie.originAttributes.firstPartyDomain, BASE_DOMAIN, "Cookie's origin attributes should be " + BASE_DOMAIN);
|
||||
}
|
||||
|
||||
// one cookie is from requesting test.js from top-level doc, and the other from
|
||||
// requesting test2.js from iframe test2.html.
|
||||
Assert.equal(count, 2, "Should have two cookies");
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
/**
|
||||
* Test for after redirect, the top-level document should update the firstPartyDomain
|
||||
* attribute. However if the redirect is happening on the iframe, the attribute
|
||||
* should remain the same.
|
||||
*/
|
||||
add_task(function* redirect_test() {
|
||||
let tab = gBrowser.addTab(BASE_URL + "test_firstParty_http_redirect.html");
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
yield ContentTask.spawn(tab.linkedBrowser, { firstPartyDomain: "example.com" }, function* (attrs) {
|
||||
info("document principal: " + content.document.nodePrincipal.origin);
|
||||
info("document uri: " + content.document.documentURI);
|
||||
|
||||
Assert.equal(content.document.documentURI, "http://example.com/browser/browser/components/originattributes/test/browser/dummy.html",
|
||||
"The page should have been redirected to http://example.com/browser/browser/components/originattributes/test/browser/dummy.html");
|
||||
Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
|
||||
attrs.firstPartyDomain, "The document should have firstPartyDomain");
|
||||
});
|
||||
|
||||
// Since this is a HTML redirect, we wait until the final page is loaded.
|
||||
let tab2 = gBrowser.addTab(BASE_URL + "test_firstParty_html_redirect.html");
|
||||
yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser, false, function(url) {
|
||||
return url == "http://example.com/";
|
||||
});
|
||||
|
||||
yield ContentTask.spawn(tab2.linkedBrowser, { firstPartyDomain: "example.com" }, function* (attrs) {
|
||||
info("2nd tab document principal: " + content.document.nodePrincipal.origin);
|
||||
info("2nd tab document uri: " + content.document.documentURI);
|
||||
Assert.equal(content.document.documentURI, "http://example.com/",
|
||||
"The page should have been redirected to http://example.com");
|
||||
Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
|
||||
attrs.firstPartyDomain, "The document should have firstPartyDomain");
|
||||
});
|
||||
|
||||
let tab3 = gBrowser.addTab(BASE_URL + "test_firstParty_iframe_http_redirect.html");
|
||||
yield BrowserTestUtils.browserLoaded(tab3.linkedBrowser, true, function(url) {
|
||||
return url == (BASE_URL + "test_firstParty_iframe_http_redirect.html");
|
||||
});
|
||||
|
||||
// This redirect happens on the iframe, so unlike the two redirect tests above,
|
||||
// the firstPartyDomain should still stick to the current top-level document,
|
||||
// which is mochi.test.
|
||||
yield ContentTask.spawn(tab3.linkedBrowser, { firstPartyDomain: "mochi.test" }, function* (attrs) {
|
||||
let iframe = content.document.getElementById("iframe1");
|
||||
info("iframe document principal: " + iframe.contentDocument.nodePrincipal.origin);
|
||||
info("iframe document uri: " + iframe.contentDocument.documentURI);
|
||||
|
||||
Assert.equal(iframe.contentDocument.documentURI, "http://example.com/browser/browser/components/originattributes/test/browser/dummy.html",
|
||||
"The page should have been redirected to http://example.com/browser/browser/components/originattributes/test/browser/dummy.html");
|
||||
Assert.equal(iframe.contentDocument.nodePrincipal.originAttributes.firstPartyDomain,
|
||||
attrs.firstPartyDomain, "The iframe should have firstPartyDomain: " + attrs.firstPartyDomain);
|
||||
});
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
gBrowser.removeTab(tab2);
|
||||
gBrowser.removeTab(tab3);
|
||||
});
|
||||
|
||||
/**
|
||||
* Test for postMessage between document and iframe.
|
||||
*/
|
||||
add_task(function* postMessage_test() {
|
||||
let tab = gBrowser.addTab(BASE_URL + "test_firstParty_postMessage.html");
|
||||
|
||||
// The top-level page will post a message to its child iframe, and wait for
|
||||
// another message from the iframe, once it receives the message, it will
|
||||
// create another iframe, dummy.html.
|
||||
// So we wait until dummy.html is loaded
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser, true, function (url) {
|
||||
return url == BASE_URL + "dummy.html";
|
||||
});
|
||||
|
||||
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
|
||||
info("document principal: " + content.document.nodePrincipal.origin);
|
||||
let value = content.document.getElementById("message").textContent;
|
||||
Assert.equal(value, "OK");
|
||||
});
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
/**
|
||||
* When the web page calls window.open, the new window should have the same
|
||||
* firstPartyDomain attribute.
|
||||
*/
|
||||
add_task(function* openWindow_test() {
|
||||
Services.prefs.setIntPref("browser.link.open_newwindow", 2);
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("browser.link.open_newwindow");
|
||||
});
|
||||
|
||||
let tab = gBrowser.addTab(BASE_URL + "window.html");
|
||||
let win = yield BrowserTestUtils.waitForNewWindow();
|
||||
|
||||
yield ContentTask.spawn(win.gBrowser.selectedBrowser, { firstPartyDomain: "mochi.test" }, function* (attrs) {
|
||||
Assert.equal(docShell.getOriginAttributes().firstPartyDomain, attrs.firstPartyDomain,
|
||||
"window.open() should have firstPartyDomain attribute");
|
||||
Assert.equal(content.document.nodePrincipal.originAttributes.firstPartyDomain,
|
||||
attrs.firstPartyDomain, "The document should have firstPartyDomain");
|
||||
|
||||
let iframe = content.document.getElementById("iframe1");
|
||||
Assert.equal(iframe.frameLoader.docShell.getOriginAttributes().firstPartyDomain,
|
||||
attrs.firstPartyDomain, "iframe's docshell should have firstPartyDomain");
|
||||
Assert.equal(iframe.contentDocument.nodePrincipal.originAttributes.firstPartyDomain,
|
||||
attrs.firstPartyDomain, "iframe should have firstPartyDomain");
|
||||
});
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
yield BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Dummy test page</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
|
||||
</head>
|
||||
<body>
|
||||
<p>Dummy test page</p>
|
||||
</body>
|
||||
</html>
|
25
browser/components/originattributes/test/browser/test.html
Normal file
25
browser/components/originattributes/test/browser/test.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1260931</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script>
|
||||
window.onmessage = function (evt) {
|
||||
if (evt.data != "HI") {
|
||||
return;
|
||||
}
|
||||
|
||||
window.parent.postMessage("OK", "http://mochi.test:8888");
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
window.parent.postMessage("KO", "http://mochi.test:8888");
|
||||
}, 1000);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Hello World.
|
||||
</body>
|
||||
</html>
|
1
browser/components/originattributes/test/browser/test.js
Normal file
1
browser/components/originattributes/test/browser/test.js
Normal file
@ -0,0 +1 @@
|
||||
var i = 1;
|
@ -0,0 +1 @@
|
||||
Set-Cookie: test=foo
|
12
browser/components/originattributes/test/browser/test2.html
Normal file
12
browser/components/originattributes/test/browser/test2.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1260931</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script src="test2.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
Hello World.
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1 @@
|
||||
var i = 1;
|
@ -0,0 +1 @@
|
||||
Set-Cookie: test2=foo
|
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Test for Bug 1260931</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<iframe id="iframe1" src="http://example.com"></iframe>
|
||||
<iframe id="iframe2" sandbox="" src="http://example.com"></iframe>
|
||||
<iframe id="iframe3" sandbox="allow-same-origin" src="http://example.com"></iframe>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1260931</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script src="test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
Hello World.
|
||||
<iframe id="iframe1" src="test2.html"></iframe>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8" http-equiv="refresh" content="0; url=http://example.com/"/>
|
||||
<title>Test for Bug 1260931</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Test for Bug 1260931</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,2 @@
|
||||
HTTP 302 Found
|
||||
Location: http://example.com/browser/browser/components/originattributes/test/browser/dummy.html
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Test for Bug 1260931</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<iframe id="iframe1" src="test_firstParty_http_redirect.html"></iframe>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Test for Bug 1260931</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<script>
|
||||
function onload() {
|
||||
let iframe1 = document.getElementById("iframe1");
|
||||
iframe1.contentWindow.postMessage("HI", "http://mochi.test:8888");
|
||||
}
|
||||
|
||||
window.onmessage = function (evt) {
|
||||
document.getElementById("message").textContent = evt.data;
|
||||
|
||||
let iframe2 = document.createElement("iframe");
|
||||
iframe2.src = "dummy.html";
|
||||
document.body.appendChild(iframe2);
|
||||
};
|
||||
</script>
|
||||
<body onload="onload()">
|
||||
<div>
|
||||
<iframe id="iframe1" src="test.html"></iframe>
|
||||
<span id="message"></span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
13
browser/components/originattributes/test/browser/window.html
Normal file
13
browser/components/originattributes/test/browser/window.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Page creating a popup</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
var w = window.open();
|
||||
w.document.body.innerHTML = "<iframe id='iframe1' src='data:text/plain,test2'></iframe>";
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -12,6 +12,7 @@
|
||||
#endif
|
||||
#include "nsIAddonPolicyService.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIEffectiveTLDService.h"
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
|
||||
@ -47,6 +48,7 @@ PrincipalOriginAttributes::InheritFromDocShellToDoc(const DocShellOriginAttribut
|
||||
mSignedPkg = aAttrs.mSignedPkg;
|
||||
|
||||
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
|
||||
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
|
||||
}
|
||||
|
||||
void
|
||||
@ -60,6 +62,7 @@ PrincipalOriginAttributes::InheritFromNecko(const NeckoOriginAttributes& aAttrs)
|
||||
mSignedPkg = aAttrs.mSignedPkg;
|
||||
|
||||
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
|
||||
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
|
||||
}
|
||||
|
||||
void
|
||||
@ -77,6 +80,7 @@ DocShellOriginAttributes::InheritFromDocToChildDocShell(const PrincipalOriginAtt
|
||||
mSignedPkg = aAttrs.mSignedPkg;
|
||||
|
||||
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
|
||||
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
|
||||
}
|
||||
|
||||
void
|
||||
@ -93,10 +97,13 @@ NeckoOriginAttributes::InheritFromDocToNecko(const PrincipalOriginAttributes& aA
|
||||
// mSignedPkg accordingly by mSignedPkgInBrowser
|
||||
|
||||
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
|
||||
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
|
||||
}
|
||||
|
||||
void
|
||||
NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs)
|
||||
NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs,
|
||||
const bool aIsTopLevelDocument,
|
||||
nsIURI* aURI)
|
||||
{
|
||||
mAppId = aAttrs.mAppId;
|
||||
mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
|
||||
@ -109,6 +116,24 @@ NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes
|
||||
// mSignedPkg accordingly by mSignedPkgInBrowser
|
||||
|
||||
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
|
||||
|
||||
bool isFirstPartyEnabled = IsFirstPartyEnabled();
|
||||
|
||||
// When the pref is on, we also compute the firstPartyDomain attribute
|
||||
// if this is for top-level document.
|
||||
if (isFirstPartyEnabled && aIsTopLevelDocument) {
|
||||
nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(tldService);
|
||||
if (!tldService) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString baseDomain;
|
||||
tldService->GetBaseDomain(aURI, 0, baseDomain);
|
||||
mFirstPartyDomain = NS_ConvertUTF8toUTF16(baseDomain);
|
||||
} else {
|
||||
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -161,6 +186,11 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
|
||||
params->Set(NS_LITERAL_STRING("privateBrowsingId"), value);
|
||||
}
|
||||
|
||||
if (!mFirstPartyDomain.IsEmpty()) {
|
||||
MOZ_RELEASE_ASSERT(mFirstPartyDomain.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
|
||||
params->Set(NS_LITERAL_STRING("firstPartyDomain"), mFirstPartyDomain);
|
||||
}
|
||||
|
||||
aStr.Truncate();
|
||||
|
||||
params->Serialize(value);
|
||||
@ -247,6 +277,12 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aName.EqualsLiteral("firstPartyDomain")) {
|
||||
MOZ_RELEASE_ASSERT(mOriginAttributes->mFirstPartyDomain.IsEmpty());
|
||||
mOriginAttributes->mFirstPartyDomain.Assign(aValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
// No other attributes are supported.
|
||||
return false;
|
||||
}
|
||||
@ -307,6 +343,21 @@ OriginAttributes::SetFromGenericAttributes(const GenericOriginAttributes& aAttrs
|
||||
mUserContextId = aAttrs.mUserContextId;
|
||||
mSignedPkg = aAttrs.mSignedPkg;
|
||||
mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
|
||||
mFirstPartyDomain = aAttrs.mFirstPartyDomain;
|
||||
}
|
||||
|
||||
bool
|
||||
OriginAttributes::IsFirstPartyEnabled()
|
||||
{
|
||||
// Cache the privacy.firstparty.isolate pref.
|
||||
static bool sFirstPartyIsolation = false;
|
||||
static bool sCachedFirstPartyPref = false;
|
||||
if (!sCachedFirstPartyPref) {
|
||||
sCachedFirstPartyPref = true;
|
||||
Preferences::AddBoolVarCache(&sFirstPartyIsolation, "privacy.firstparty.isolate");
|
||||
}
|
||||
|
||||
return sFirstPartyIsolation;
|
||||
}
|
||||
|
||||
BasePrincipal::BasePrincipal()
|
||||
|
@ -37,7 +37,8 @@ public:
|
||||
mAddonId == aOther.mAddonId &&
|
||||
mUserContextId == aOther.mUserContextId &&
|
||||
mSignedPkg == aOther.mSignedPkg &&
|
||||
mPrivateBrowsingId == aOther.mPrivateBrowsingId;
|
||||
mPrivateBrowsingId == aOther.mPrivateBrowsingId &&
|
||||
mFirstPartyDomain == aOther.mFirstPartyDomain;
|
||||
}
|
||||
bool operator!=(const OriginAttributes& aOther) const
|
||||
{
|
||||
@ -65,6 +66,9 @@ protected:
|
||||
OriginAttributes() {}
|
||||
explicit OriginAttributes(const OriginAttributesDictionary& aOther)
|
||||
: OriginAttributesDictionary(aOther) {}
|
||||
|
||||
// check if "privacy.firstparty.isolate" is enabled.
|
||||
bool IsFirstPartyEnabled();
|
||||
};
|
||||
|
||||
class PrincipalOriginAttributes;
|
||||
@ -136,7 +140,11 @@ public:
|
||||
// is made.
|
||||
void InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs);
|
||||
|
||||
void InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs);
|
||||
// Inheriting OriginAttributes from a docshell when loading a top-level
|
||||
// document.
|
||||
void InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs,
|
||||
const bool aIsTopLevelDocument = false,
|
||||
nsIURI* aURI = nullptr);
|
||||
};
|
||||
|
||||
// For operating on OriginAttributes not associated with any data structure.
|
||||
@ -189,6 +197,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mFirstPartyDomain.WasPassed() && mFirstPartyDomain.Value() != aAttrs.mFirstPartyDomain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -225,6 +237,11 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mFirstPartyDomain.WasPassed() && aOther.mFirstPartyDomain.WasPassed() &&
|
||||
mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -437,37 +437,20 @@ nsScriptSecurityManager::GetChannelURIPrincipal(nsIChannel* aChannel,
|
||||
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsILoadContext> loadContext;
|
||||
NS_QueryNotificationCallbacks(aChannel, loadContext);
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
|
||||
nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_INVALID;
|
||||
if (loadInfo) {
|
||||
contentPolicyType = loadInfo->GetExternalContentPolicyType();
|
||||
}
|
||||
|
||||
// Inherit the origin attributes from loadInfo.
|
||||
// If this is a top-level document load, the origin attributes of the
|
||||
// loadInfo will be set from nsDocShell::DoURILoad.
|
||||
// For subresource loading, the origin attributes of the loadInfo is from
|
||||
// its loadingPrincipal.
|
||||
PrincipalOriginAttributes attrs;
|
||||
if (nsIContentPolicy::TYPE_DOCUMENT == contentPolicyType ||
|
||||
nsIContentPolicy::TYPE_SUBDOCUMENT == contentPolicyType) {
|
||||
// If it's document or sub-document, inherit originAttributes from
|
||||
// the document.
|
||||
if (loadContext) {
|
||||
DocShellOriginAttributes docShellAttrs;
|
||||
loadContext->GetOriginAttributes(docShellAttrs);
|
||||
attrs.InheritFromDocShellToDoc(docShellAttrs, uri);
|
||||
}
|
||||
} else {
|
||||
// Inherit origin attributes from loading principal if any.
|
||||
nsCOMPtr<nsIPrincipal> loadingPrincipal;
|
||||
if (loadInfo) {
|
||||
loadInfo->GetLoadingPrincipal(getter_AddRefs(loadingPrincipal));
|
||||
}
|
||||
if (loadingPrincipal) {
|
||||
attrs = BasePrincipal::Cast(loadingPrincipal)->OriginAttributesRef();
|
||||
}
|
||||
}
|
||||
|
||||
// For addons loadInfo might be null.
|
||||
if (loadInfo) {
|
||||
attrs.InheritFromNecko(loadInfo->GetOriginAttributes());
|
||||
}
|
||||
rv = MaybeSetAddonIdFromURI(attrs, uri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
|
||||
|
@ -42,7 +42,9 @@ function printAttrs(name, attrs) {
|
||||
"\tuserContextId: " + attrs.userContextId + ",\n" +
|
||||
"\tinIsolatedMozBrowser: " + attrs.inIsolatedMozBrowser + ",\n" +
|
||||
"\taddonId: '" + attrs.addonId + "',\n" +
|
||||
"\tsignedPkg: '" + attrs.signedPkg + "'\n}");
|
||||
"\tsignedPkg: '" + attrs.signedPkg + "',\n" +
|
||||
"\tprivateBrowsingId: '" + attrs.privateBrowsingId + "',\n" +
|
||||
"\tfirstPartyDomain: '" + attrs.firstPartyDomain + "'\n}");
|
||||
}
|
||||
|
||||
|
||||
@ -55,6 +57,8 @@ function checkValues(attrs, values) {
|
||||
do_check_eq(attrs.inIsolatedMozBrowser, values.inIsolatedMozBrowser || false);
|
||||
do_check_eq(attrs.addonId, values.addonId || '');
|
||||
do_check_eq(attrs.signedPkg, values.signedPkg || '');
|
||||
do_check_eq(attrs.privateBrowsingId, values.privateBrowsingId || '');
|
||||
do_check_eq(attrs.firstPartyDomain, values.firstPartyDomain || '');
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
@ -122,6 +126,11 @@ function run_test() {
|
||||
checkOriginAttributes(exampleOrg_addon, { addonId: "dummy" }, '^addonId=dummy');
|
||||
do_check_eq(exampleOrg_addon.origin, 'http://example.org^addonId=dummy');
|
||||
|
||||
// First party Uri
|
||||
var exampleOrg_firstPartyDomain = ssm.createCodebasePrincipal(makeURI('http://example.org'), {firstPartyDomain: 'example.org'});
|
||||
checkOriginAttributes(exampleOrg_firstPartyDomain, { firstPartyDomain: "example.org" }, '^firstPartyDomain=example.org');
|
||||
do_check_eq(exampleOrg_firstPartyDomain.origin, 'http://example.org^firstPartyDomain=example.org');
|
||||
|
||||
// Make sure we don't crash when serializing principals with UNKNOWN_APP_ID.
|
||||
try {
|
||||
let binaryStream = Cc["@mozilla.org/binaryoutputstream;1"].
|
||||
@ -177,6 +186,7 @@ function run_test() {
|
||||
checkCrossOrigin(exampleOrg_appBrowser, nullPrin_appBrowser);
|
||||
checkCrossOrigin(exampleOrg_appBrowser, exampleCom_appBrowser);
|
||||
checkCrossOrigin(exampleOrg_addon, exampleOrg);
|
||||
checkCrossOrigin(exampleOrg_firstPartyDomain, exampleOrg);
|
||||
checkCrossOrigin(exampleOrg_userContext, exampleOrg);
|
||||
checkCrossOrigin(exampleOrg_userContextAddon, exampleOrg);
|
||||
checkCrossOrigin(exampleOrg_userContext, exampleOrg_userContextAddon);
|
||||
@ -203,7 +213,7 @@ function run_test() {
|
||||
|
||||
// check that we can create an empty origin attributes dict with default
|
||||
// members and values.
|
||||
emptyAttrs = ChromeUtils.fillNonDefaultOriginAttributes({});
|
||||
var emptyAttrs = ChromeUtils.fillNonDefaultOriginAttributes({});
|
||||
checkValues(emptyAttrs);
|
||||
|
||||
var uri = "http://example.org";
|
||||
@ -213,19 +223,20 @@ function run_test() {
|
||||
[ "^userContextId=3", {userContextId: 3} ],
|
||||
[ "^addonId=fooBar", {addonId: "fooBar"} ],
|
||||
[ "^inBrowser=1", {inIsolatedMozBrowser: true} ],
|
||||
[ "^firstPartyDomain=example.org", {firstPartyDomain: "example.org"} ],
|
||||
[ "^signedPkg=bazQux", {signedPkg: "bazQux"} ],
|
||||
[ "^appId=3&inBrowser=1&userContextId=6",
|
||||
{appId: 3, userContextId: 6, inIsolatedMozBrowser: true} ] ];
|
||||
|
||||
// check that we can create an origin attributes from an origin properly
|
||||
tests.forEach(function(t) {
|
||||
tests.forEach(t => {
|
||||
let attrs = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
|
||||
checkValues(attrs, t[1]);
|
||||
do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), t[0]);
|
||||
});
|
||||
|
||||
// check that we can create an origin attributes from a dict properly
|
||||
tests.forEach(function(t) {
|
||||
tests.forEach(t => {
|
||||
let attrs = ChromeUtils.fillNonDefaultOriginAttributes(t[1]);
|
||||
checkValues(attrs, t[1]);
|
||||
do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), t[0]);
|
||||
@ -244,7 +255,7 @@ function run_test() {
|
||||
[ "^appId=5", {appId: 5}, {appId: 3, userContextId: 7}, {appId: 3, userContextId: 7}, "^appId=3&userContextId=7" ] ];
|
||||
|
||||
// check that we can set origin attributes values properly
|
||||
set_tests.forEach(function(t) {
|
||||
set_tests.forEach(t => {
|
||||
let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
|
||||
checkValues(orig, t[1]);
|
||||
let mod = orig;
|
||||
@ -267,7 +278,7 @@ function run_test() {
|
||||
[ "^appId=5&userContextId=3", {appId: 5, userContextId: 3}, {appId: 5}, "^appId=5" ] ];
|
||||
|
||||
// check that we can set the userContextId to default properly
|
||||
dflt_tests.forEach(function(t) {
|
||||
dflt_tests.forEach(t => {
|
||||
let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
|
||||
checkValues(orig, t[1]);
|
||||
let mod = orig;
|
||||
@ -275,4 +286,26 @@ function run_test() {
|
||||
checkValues(mod, t[2]);
|
||||
do_check_eq(ChromeUtils.originAttributesToSuffix(mod), t[3]);
|
||||
});
|
||||
|
||||
// each row in the dflt2_tests array has these values:
|
||||
// [0] - the suffix used to create an origin attribute from
|
||||
// [1] - the expected result of creating an origin attributes from [0]
|
||||
// [2] - the expected result after setting firstPartyUri to the default
|
||||
// [3] - the expected result of creating a suffix from [2]
|
||||
var dflt2_tests = [
|
||||
[ "", {}, {}, "" ],
|
||||
[ "^firstPartyDomain=foo.com", {firstPartyDomain: "foo.com"}, {}, "" ],
|
||||
[ "^appId=5", {appId: 5}, {appId: 5}, "^appId=5" ],
|
||||
[ "^appId=5&firstPartyDomain=foo.com", {appId: 5, firstPartyDomain: "foo.com"}, {appId: 5}, "^appId=5" ] ];
|
||||
|
||||
// check that we can set the userContextId to default properly
|
||||
dflt2_tests.forEach(t => {
|
||||
let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
|
||||
checkValues(orig, t[1]);
|
||||
let mod = orig;
|
||||
mod['firstPartyDomain'] = "";
|
||||
checkValues(mod, t[2]);
|
||||
do_check_eq(ChromeUtils.originAttributesToSuffix(mod), t[3]);
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -10812,7 +10812,10 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
// OriginAttributes of the parent document. Or in case there isn't a
|
||||
// parent document.
|
||||
NeckoOriginAttributes neckoAttrs;
|
||||
neckoAttrs.InheritFromDocShellToNecko(GetOriginAttributes());
|
||||
bool isTopLevelDoc = aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT &&
|
||||
mItemType == typeContent &&
|
||||
!GetIsMozBrowserOrApp();
|
||||
neckoAttrs.InheritFromDocShellToNecko(GetOriginAttributes(), isTopLevelDoc, aURI);
|
||||
rv = loadInfo->SetOriginAttributes(neckoAttrs);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -2098,6 +2098,38 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
attrs = nsDocShell::Cast(docShell)->GetOriginAttributes();
|
||||
}
|
||||
|
||||
// Inherit origin attributes from parent document if
|
||||
// 1. It's in a content docshell.
|
||||
// 2. its nodePrincipal is not a SystemPrincipal.
|
||||
// 3. It's not a mozbrowser nor mozapp frame.
|
||||
//
|
||||
// For example, firstPartyDomain is computed from top-level document, it
|
||||
// doesn't exist in the top-level docshell.
|
||||
if (parentType == nsIDocShellTreeItem::typeContent &&
|
||||
!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()) &&
|
||||
!OwnerIsMozBrowserOrAppFrame()) {
|
||||
PrincipalOriginAttributes poa = BasePrincipal::Cast(doc->NodePrincipal())->OriginAttributesRef();
|
||||
|
||||
// Assert on the firstPartyDomain from top-level docshell should be empty
|
||||
if (mIsTopLevelContent) {
|
||||
MOZ_ASSERT(attrs.mFirstPartyDomain.IsEmpty(),
|
||||
"top-level docshell shouldn't have firstPartyDomain attribute.");
|
||||
}
|
||||
|
||||
// So far we want to make sure InheritFromDocToChildDocShell doesn't override
|
||||
// any other origin attribute than firstPartyDomain.
|
||||
MOZ_ASSERT(attrs.mAppId == poa.mAppId,
|
||||
"docshell and document should have the same appId attribute.");
|
||||
MOZ_ASSERT(attrs.mUserContextId == poa.mUserContextId,
|
||||
"docshell and document should have the same userContextId attribute.");
|
||||
MOZ_ASSERT(attrs.mInIsolatedMozBrowser == poa.mInIsolatedMozBrowser,
|
||||
"docshell and document should have the same inIsolatedMozBrowser attribute.");
|
||||
MOZ_ASSERT(attrs.mPrivateBrowsingId == poa.mPrivateBrowsingId,
|
||||
"docshell and document should have the same privateBrowsingId attribute.");
|
||||
|
||||
attrs.InheritFromDocToChildDocShell(poa);
|
||||
}
|
||||
|
||||
if (OwnerIsAppFrame()) {
|
||||
// You can't be both an app and a browser frame.
|
||||
MOZ_ASSERT(!OwnerIsMozBrowserFrame());
|
||||
|
@ -81,6 +81,7 @@ dictionary OriginAttributesDictionary {
|
||||
DOMString addonId = "";
|
||||
DOMString signedPkg = "";
|
||||
unsigned long privateBrowsingId = 0;
|
||||
DOMString firstPartyDomain = "";
|
||||
};
|
||||
dictionary OriginAttributesPatternDictionary {
|
||||
unsigned long appId;
|
||||
@ -89,4 +90,5 @@ dictionary OriginAttributesPatternDictionary {
|
||||
DOMString addonId;
|
||||
DOMString signedPkg;
|
||||
unsigned long privateBrowsingId;
|
||||
DOMString firstPartyDomain;
|
||||
};
|
||||
|
@ -148,6 +148,7 @@ NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
|
||||
aAttrs.mSignedPkg = aSerialized.mOriginAttributes.mSignedPkg;
|
||||
aAttrs.mUserContextId = aSerialized.mOriginAttributes.mUserContextId;
|
||||
aAttrs.mPrivateBrowsingId = aSerialized.mOriginAttributes.mPrivateBrowsingId;
|
||||
aAttrs.mFirstPartyDomain = aSerialized.mOriginAttributes.mFirstPartyDomain;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2901,6 +2901,36 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
if (mLoadInfo) {
|
||||
nsCOMPtr<nsILoadInfo> newLoadInfo =
|
||||
static_cast<mozilla::LoadInfo*>(mLoadInfo.get())->Clone();
|
||||
|
||||
// re-compute the origin attributes of the loadInfo if it's top-level load.
|
||||
bool isTopLevelDoc =
|
||||
newLoadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_DOCUMENT;
|
||||
|
||||
if (isTopLevelDoc) {
|
||||
nsCOMPtr<nsILoadContext> loadContext;
|
||||
NS_QueryNotificationCallbacks(this, loadContext);
|
||||
DocShellOriginAttributes docShellAttrs;
|
||||
if (loadContext) {
|
||||
loadContext->GetOriginAttributes(docShellAttrs);
|
||||
}
|
||||
MOZ_ASSERT(docShellAttrs.mFirstPartyDomain.IsEmpty(),
|
||||
"top-level docshell shouldn't have firstPartyDomain attribute.");
|
||||
|
||||
NeckoOriginAttributes attrs = newLoadInfo->GetOriginAttributes();
|
||||
|
||||
MOZ_ASSERT(docShellAttrs.mAppId == attrs.mAppId,
|
||||
"docshell and necko should have the same appId attribute.");
|
||||
MOZ_ASSERT(docShellAttrs.mUserContextId == attrs.mUserContextId,
|
||||
"docshell and necko should have the same userContextId attribute.");
|
||||
MOZ_ASSERT(docShellAttrs.mInIsolatedMozBrowser == attrs.mInIsolatedMozBrowser,
|
||||
"docshell and necko should have the same inIsolatedMozBrowser attribute.");
|
||||
MOZ_ASSERT(docShellAttrs.mPrivateBrowsingId == attrs.mPrivateBrowsingId,
|
||||
"docshell and necko should have the same privateBrowsingId attribute.");
|
||||
|
||||
attrs.InheritFromDocShellToNecko(docShellAttrs, true, newURI);
|
||||
newLoadInfo->SetOriginAttributes(attrs);
|
||||
}
|
||||
|
||||
bool isInternalRedirect =
|
||||
(redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
|
||||
nsIChannelEventSink::REDIRECT_STS_UPGRADE));
|
||||
|
Loading…
Reference in New Issue
Block a user