Commit a9bf408f authored by Kathleen Brade's avatar Kathleen Brade Committed by Georg Koppen
Browse files

Bug 16620: Clear window.name when no referrer sent

Convert JS implementation (within Torbutton) to a C++ browser patch.
parent 388c91b8
......@@ -7467,11 +7467,71 @@ nsresult nsDocShell::CreateContentViewer(const nsACString& aContentType,
aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
}
FirePageHideNotification(!mSavingOldViewer);
if (mIsBeingDestroyed) {
// Force to stop the newly created orphaned viewer.
viewer->Stop();
return NS_ERROR_DOCSHELL_DYING;
}
// Tor bug 16620: Clear window.name of top-level documents if
// there is no referrer. We make an exception for new windows,
// e.g., window.open(url, "MyName").
bool isNewWindowTarget = false;
nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aRequest, &rv));
if (props) {
props->GetPropertyAsBool(NS_LITERAL_STRING("docshell.newWindowTarget"),
&isNewWindowTarget);
}
if (!isNewWindowTarget) {
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aOpenedChannel));
nsCOMPtr<nsIURI> httpReferrer;
if (httpChannel) {
nsCOMPtr<nsIReferrerInfo> referrerInfo;
rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
NS_ENSURE_SUCCESS(rv, rv);
if (referrerInfo) {
// We want GetComputedReferrer() instead of GetOriginalReferrer(), since
// the former takes into consideration referrer policy, protocol
// whitelisting...
httpReferrer = referrerInfo->GetComputedReferrer();
}
}
bool isTopFrame = mBrowsingContext->IsTop();
#ifdef DEBUG_WINDOW_NAME
printf("DOCSHELL %p CreateContentViewer - possibly clearing window.name:\n",
this);
printf(" current window.name: \"%s\"\n",
NS_ConvertUTF16toUTF8(mName).get());
nsAutoCString curSpec, loadingSpec;
if (this->mCurrentURI) mCurrentURI->GetSpec(curSpec);
if (mLoadingURI) mLoadingURI->GetSpec(loadingSpec);
printf(" current URI: %s\n", curSpec.get());
printf(" loading URI: %s\n", loadingSpec.get());
printf(" is top document: %s\n", isTopFrame ? "Yes" : "No");
if (!httpReferrer) {
printf(" referrer: None\n");
} else {
nsAutoCString refSpec;
httpReferrer->GetSpec(refSpec);
printf(" referrer: %s\n", refSpec.get());
}
#endif
bool clearName = isTopFrame && !httpReferrer;
if (clearName) SetName(NS_LITERAL_STRING(""));
#ifdef DEBUG_WINDOW_NAME
printf(" action taken: %s window.name\n",
clearName ? "Cleared" : "Preserved");
#endif
}
mLoadingURI = nullptr;
// Set mFiredUnloadEvent = false so that the unload handler for the
......
......@@ -52,6 +52,8 @@ support-files =
start_historyframe.html
url1_historyframe.html
url2_historyframe.html
tor_bug16620.html
tor_bug16620_form.html
[test_anchor_scroll_after_document_open.html]
[test_bfcache_plus_hash.html]
......@@ -115,6 +117,7 @@ support-files = file_bug675587.html
[test_framedhistoryframes.html]
support-files = file_framedhistoryframes.html
[test_pushState_after_document_open.html]
[test_tor_bug16620.html]
[test_windowedhistoryframes.html]
[test_triggeringprincipal_location_seturi.html]
[test_bug1507702.html]
<!DOCTYPE HTML>
<html>
<!--
Tor Bug 16620: Clear window.name when no referrer sent.
https://trac.torproject.org/projects/tor/ticket/16620
-->
<meta charset="utf-8">
<head>
<title>Test for Tor Bug 16620 - Clear window.name when no referrer sent</title>
<script type="application/javascript"
src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://trac.torproject.org/projects/tor/ticket/16620">Tor Bug 16620</a>
<script type="application/javascript;version=1.7">
// ## Test constants
const kTestPath = "/tests/docshell/test/mochitest/";
const kLinkFile = "tor_bug16620.html";
const kFormFile = "tor_bug16620_form.html";
const kBaseURL1 = "http://example.com";
const kBaseURL1_https = "https://example.com";
const kBaseURL2 = "http://example.net";
const kSendReferrerPref = "network.http.sendRefererHeader";
const kSendReferrerNever = 0;
const kSendReferrerForUserAction = 1;
const kSendReferrerAlways = 2;
let gTests = [
// Test #1: Same domain; never send referrer.
{ startURL: kBaseURL1, destURL: kBaseURL1,
referrerPref: kSendReferrerNever,
expectIsolation: true },
// Test #2: Same domain; send referrer upon user action.
{ startURL: kBaseURL1, destURL: kBaseURL1,
referrerPref: kSendReferrerForUserAction,
expectIsolation: false },
// Test #3: Same domain; always send referrer.
{ startURL: kBaseURL1, destURL: kBaseURL1,
referrerPref: kSendReferrerAlways,
expectIsolation: false },
// Test #4: Different top-level domains; never send referrer.
{ startURL: kBaseURL1, destURL: kBaseURL2,
referrerPref: kSendReferrerNever,
expectIsolation: true },
// Test #5: Different top-level domains; send referrer upon user action.
{ startURL: kBaseURL1, destURL: kBaseURL2,
referrerPref: kSendReferrerForUserAction,
expectIsolation: false },
// Test #6: Different top-level domains; always send referrer.
{ startURL: kBaseURL1, destURL: kBaseURL2,
referrerPref: kSendReferrerAlways,
expectIsolation: false },
// Test #7: https -> http transition.
{ startURL: kBaseURL1_https, destURL: kBaseURL1,
referrerPref: kSendReferrerForUserAction,
expectIsolation: true },
// Test #8: Same domain, rel="noreferrer" on link.
{ startURL: kBaseURL1, destURL: kBaseURL1, noReferrerOnLink: true,
referrerPref: kSendReferrerAlways,
expectIsolation: true },
// Test #9: Same domain, "no-referrer" meta tag in document.
{ startURL: kBaseURL1, destURL: kBaseURL1, noReferrerInMetaTag: true,
referrerPref: kSendReferrerAlways,
expectIsolation: true },
// Test #10: Like test #9, but reset window.name during unload.
// (similar to http://www.thomasfrank.se/sessvarsTestPage1.html)
{ startURL: kBaseURL1, destURL: kBaseURL1, noReferrerInMetaTag: true,
resetInUnload: true,
referrerPref: kSendReferrerAlways,
expectIsolation: true },
// Test #11: Data URL as destination (no referrer).
{ startURL: kBaseURL1,
referrerPref: kSendReferrerAlways,
expectIsolation: true },
// Test #12: Ensure that window.name is preserved when a dynamically loaded
// iframe is used to perform a form post (regression test for Tor bug 18168).
{ startURL: kBaseURL1,
isFormTest: true,
referrerPref: kSendReferrerAlways,
expectIsolation: false },
];
let gCurTest = 0;
let gCurWinName, gChildWin, gDataURL;
// ## Utility functions
function generateRandomName()
{
// Generate a random 6 character string using 0-9 and a-z.
return ((1 + Math.random()).toString(36) + '000000').substr(2, 6);
}
function startNextTest() {
++gCurTest;
if (gCurTest > gTests.length) {
SimpleTest.finish();
} else {
let curTest = gTests[gCurTest - 1];
if ("referrerPref" in curTest)
SpecialPowers.setIntPref(kSendReferrerPref, curTest.referrerPref);
else
SpecialPowers.setIntPref(kSendReferrerPref, kSendReferrerForUserAction);
gCurWinName = generateRandomName();
let url = curTest.startURL + kTestPath;
if (curTest.isFormTest === true) {
url += kFormFile + "?" + gCurWinName;
gChildWin = window.open(url, undefined);
} else {
url += kLinkFile + "?firstDocLoaded";
gChildWin = window.open(url, gCurWinName);
}
}
}
// ## Add a message event listener.
window.addEventListener("message", function(aEvent) {
if (aEvent.source !== gChildWin)
return;
// console.log("parent received message:" + JSON.stringify(aEvent.data));
let proceedToNextTest = false;
let curTest = gTests[gCurTest - 1];
let state = aEvent.data.state;
let winName = aEvent.data.winName;
if ("firstDocLoaded" == state) {
// Process response from step one of the link-based tests.
let step1Passed = (winName === gCurWinName);
if (!step1Passed) {
ok(step1Passed, "Test #" + gCurTest +
" - first document's name matches window.open parameter");
proceedToNextTest = true;
}
// Send an "openURL" message to the loaded document.
let url2 = (curTest.destURL)
? curTest.destURL + kTestPath + kLinkFile + "?secondDocLoaded"
: gDataURL;
let noReferrerOnLink = (curTest.noReferrerOnLink === true);
let noReferrerInMetaTag = (curTest.noReferrerInMetaTag === true);
let resetInUnload = (curTest.resetInUnload === true);
aEvent.source.postMessage({ action: "openURL", url: url2,
noReferrerOnLink: noReferrerOnLink,
noReferrerInMetaTag: noReferrerInMetaTag,
resetInUnload: resetInUnload },
aEvent.origin);
} else if ("secondDocLoaded" == state) {
// Process response from step two of the link-based tests.
if (curTest.expectIsolation) {
ok(winName === "",
"Test #" + gCurTest + " - second document: name was cleared");
} else {
ok(winName === gCurWinName,
"Test #" + gCurTest + " - second document: name was preserved");
}
proceedToNextTest = true;
} else if ("formPostDone" == state) {
// Process response from the form post tests.
if (curTest.expectIsolation) {
ok(winName === "",
"Test #" + gCurTest + " - iframe form post: name was cleared");
} else {
ok(winName === gCurWinName,
"Test #" + gCurTest + " - iframe form post: name was preserved");
}
proceedToNextTest = true;
}
if (proceedToNextTest) {
gChildWin.close();
startNextTest();
}
}, false);
SimpleTest.waitForExplicitFinish();
if (SpecialPowers.getBoolPref("security.nocertdb")) {
// Mochitests don't simulate https correctly with "security.nocertdb"
// enabled. See https://bugs.torproject.org/18087
ok(false, "Please disable the pref `security.nocertdb` before running this test.");
SimpleTest.finish();
} else {
// Read file contents, construct a data URL (used by some tests), and
// then start the first test.
let url = kTestPath + kLinkFile;
let xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = function() {
gDataURL = "data:text/html;charset=utf-8,"
+ encodeURIComponent(this.responseText);
startNextTest();
}
xhr.send();
}
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<!--
Tor Bug 16620: Clear window.name when no referrer sent.
https://trac.torproject.org/projects/tor/ticket/16620
-->
<head>
<meta charset="UTF-8">
<title>Supporting Doc for Tor Bug 16620 Tests</title>
</head>
<body>
<a id="link" href="">secondDoc</a>
<script type="application/javascript;version=1.7">
// Extract test state from our query string, defaulting to
// "secondDocLoaded" to support use of this HTML content within
// a data URI (where query strings are not supported).
let state = (location.search.length > 0) ? location.search.substr(1)
: "secondDocLoaded";
// Notify the test driver.
opener.postMessage({ state: state, winName: window.name }, "*");
// Add a message event listener to process "openURL" actions.
window.addEventListener("message", function(aEvent) {
if (aEvent.data.action == "openURL") {
if (aEvent.data.noReferrerInMetaTag) {
let metaElem = document.createElement("meta");
metaElem.name = "referrer";
metaElem.content = "no-referrer";
document.head.appendChild(metaElem);
}
let linkElem = document.getElementById("link");
linkElem.href = aEvent.data.url;
if (aEvent.data.noReferrerOnLink)
linkElem.rel = "noreferrer";
if (aEvent.data.resetInUnload) {
let tmpName = window.name;
window.addEventListener("unload", function() {
window.name = tmpName;
}, false);
}
linkElem.click();
}
}, false);
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<!--
Tor Bug 16620: Clear window.name when no referrer sent.
https://trac.torproject.org/projects/tor/ticket/16620
Regression test for bug 18168: iframe-based AJAX call opening in new tab
-->
<head>
<meta charset="UTF-8">
<title>Supporting Form-based Doc for Tor Bug 16620 Tests</title>
</head>
<body>
<script type="application/javascript;version=1.7">
document.addEventListener("DOMContentLoaded", function () {
addPostTarget();
}, false);
function addPostTarget()
{
let frameName = location.search.substr(1);
let form = document.getElementById("postform");
let iframe = document.createElement("iframe");
iframe.style.border = "1px solid red";
iframe.src = "about:blank";
form.target = iframe.name = iframe.id = frameName;
document.body.appendChild(iframe);
let didSubmit = false;
iframe.onload = function() {
if (!didSubmit) {
didSubmit = true;
let submitButton = document.getElementById("submitButton");
submitButton.click();
} else {
// Form submission complete. Report iframe's name to test driver.
opener.postMessage({ state: "formPostDone", winName: iframe.name }, "*");
}
};
}
</script>
<form name="postform" id="postform"
action="data:text/plain;charset=utf-8,Hello%20world"
method="POST" enctype="multipart/form-data">
<input type="hidden" name="field1" value="value1"><br>
<input id="submitButton" type="submit" value="Post It">
</body>
</html>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment