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:
Sebastian Hengst 2016-09-02 14:55:59 +02:00
parent 7db44d87f4
commit 31c5f85098
27 changed files with 532 additions and 38 deletions

View File

@ -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

View File

@ -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]

View File

@ -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);
});

View File

@ -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>

View 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>

View File

@ -0,0 +1 @@
var i = 1;

View File

@ -0,0 +1 @@
Set-Cookie: test=foo

View 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>

View File

@ -0,0 +1 @@
var i = 1;

View File

@ -0,0 +1 @@
Set-Cookie: test2=foo

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>Test for Bug 1260931</title>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,2 @@
HTTP 302 Found
Location: http://example.com/browser/browser/components/originattributes/test/browser/dummy.html

View File

@ -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>

View File

@ -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>

View 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>

View File

@ -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()

View File

@ -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;
}
};

View File

@ -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);

View File

@ -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]);
});
}

View File

@ -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;

View File

@ -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());

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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));