summaryrefslogtreecommitdiffstats
path: root/docshell
diff options
context:
space:
mode:
Diffstat (limited to 'docshell')
-rw-r--r--docshell/base/nsDocShell.cpp78
-rw-r--r--docshell/base/nsDocShell.h6
-rw-r--r--docshell/base/nsILinkHandler.h10
-rw-r--r--docshell/base/nsIWebNavigation.idl23
-rw-r--r--docshell/shistory/nsSHEntry.cpp3
-rw-r--r--docshell/shistory/nsSHistory.cpp3
-rw-r--r--docshell/test/browser/browser.ini3
-rw-r--r--docshell/test/browser/browser_click_link_within_view_source.js60
-rw-r--r--docshell/test/browser/browser_history_triggeringprincipal_viewsource.js50
-rw-r--r--docshell/test/browser/dummy_page.html6
-rw-r--r--docshell/test/browser/file_click_link_within_view_source.html6
-rw-r--r--docshell/test/dummy_page.html6
-rw-r--r--docshell/test/mochitest.ini2
-rw-r--r--docshell/test/test_triggeringprincipal_location_seturi.html102
14 files changed, 317 insertions, 41 deletions
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index bd2a8a433..b3e26da33 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1644,7 +1644,7 @@ nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
uri,
aStream,
triggeringPrincipal,
- nsILoadInfo::SEC_NORMAL,
+ nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
nsIContentPolicy::TYPE_OTHER,
aContentType,
aContentCharset);
@@ -4732,7 +4732,7 @@ nsDocShell::LoadURI(const char16_t* aURI,
{
return LoadURIWithOptions(aURI, aLoadFlags, aReferringURI,
mozilla::net::RP_Default, aPostStream,
- aHeaderStream, nullptr);
+ aHeaderStream, nullptr, nullptr);
}
NS_IMETHODIMP
@@ -4742,7 +4742,8 @@ nsDocShell::LoadURIWithOptions(const char16_t* aURI,
uint32_t aReferrerPolicy,
nsIInputStream* aPostStream,
nsIInputStream* aHeaderStream,
- nsIURI* aBaseURI)
+ nsIURI* aBaseURI,
+ nsIPrincipal* aTriggeringPrincipal)
{
NS_ASSERTION((aLoadFlags & 0xf) == 0, "Unexpected flags");
@@ -4861,6 +4862,7 @@ nsDocShell::LoadURIWithOptions(const char16_t* aURI,
loadInfo->SetReferrerPolicy(aReferrerPolicy);
loadInfo->SetHeadersStream(aHeaderStream);
loadInfo->SetBaseURI(aBaseURI);
+ loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
loadInfo->SetForceAllowDataURI(forceAllowDataURI);
if (fixupInfo) {
@@ -5687,6 +5689,11 @@ nsDocShell::LoadPage(nsISupports* aPageDescriptor, uint32_t aDisplayType)
}
shEntry->SetURI(newUri);
shEntry->SetOriginalURI(nullptr);
+ // shEntry's current triggering principal is whoever loaded that page initially.
+ // But now we're doing another load of the page, via an API that is only exposed
+ // to system code. The triggering principal for this load should be the system
+ // principal.
+ shEntry->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
}
rv = LoadHistoryEntry(shEntry, LOAD_HISTORY);
@@ -9145,8 +9152,13 @@ nsDocShell::CreateContentViewer(const nsACString& aContentType,
// Make sure we have a URI to set currentURI.
nsCOMPtr<nsIURI> failedURI;
+ nsCOMPtr<nsIPrincipal> triggeringPrincipal;
if (failedChannel) {
NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
+ } else {
+ // if there is no failed channel we have to explicitly provide
+ // a triggeringPrincipal for the history entry.
+ triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
}
if (!failedURI) {
@@ -9167,7 +9179,8 @@ nsDocShell::CreateContentViewer(const nsACString& aContentType,
// Create an shistory entry for the old load.
if (failedURI) {
bool errorOnLocationChangeNeeded = OnNewURI(
- failedURI, failedChannel, nullptr, nullptr, mLoadType, false, false, false);
+ failedURI, failedChannel, triggeringPrincipal,
+ nullptr, mLoadType, false, false, false);
if (errorOnLocationChangeNeeded) {
FireOnLocationChange(this, failedChannel, failedURI,
@@ -10394,10 +10407,13 @@ nsDocShell::InternalLoad(nsIURI* aURI,
* call OnNewURI() so that, this traversal will be
* recorded in session and global history.
*/
- nsCOMPtr<nsIPrincipal> triggeringPrincipal, principalToInherit;
+ nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit;
if (mOSHE) {
- mOSHE->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
- mOSHE->GetPrincipalToInherit(getter_AddRefs(principalToInherit));
+ mOSHE->GetTriggeringPrincipal(getter_AddRefs(newURITriggeringPrincipal));
+ mOSHE->GetPrincipalToInherit(getter_AddRefs(newURIPrincipalToInherit));
+ } else {
+ newURITriggeringPrincipal = aTriggeringPrincipal;
+ newURIPrincipalToInherit = doc->NodePrincipal();
}
// Pass true for aCloneSHChildren, since we're not
// changing documents here, so all of our subframes are
@@ -10407,7 +10423,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
// flag on firing onLocationChange(...).
// Anyway, aCloneSHChildren param is simply reflecting
// doShortCircuitedLoad in this scope.
- OnNewURI(aURI, nullptr, triggeringPrincipal, principalToInherit,
+ OnNewURI(aURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
mLoadType, true, true, true);
nsCOMPtr<nsIInputStream> postData;
@@ -10606,7 +10622,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
}
bool shouldLoad;
rv = browserChrome3->ShouldLoadURI(this, uriForShouldLoadCheck, aReferrer,
- &shouldLoad);
+ aTriggeringPrincipal, &shouldLoad);
if (NS_SUCCEEDED(rv) && !shouldLoad) {
return NS_OK;
}
@@ -10961,7 +10977,8 @@ nsDocShell::DoURILoad(nsIURI* aURI,
}
nsLoadFlags loadFlags = mDefaultLoadFlags;
- nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
+ nsSecurityFlags securityFlags =
+ nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
if (aFirstParty) {
// tag first party URL loads
@@ -12123,7 +12140,9 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
// Since we're not changing which page we have loaded, pass
// true for aCloneChildren.
- rv = AddToSessionHistory(newURI, nullptr, nullptr, nullptr, true,
+ rv = AddToSessionHistory(newURI, nullptr,
+ document->NodePrincipal(), // triggeringPrincipal
+ nullptr, true,
getter_AddRefs(newSHEntry));
NS_ENSURE_SUCCESS(rv, rv);
@@ -12399,11 +12418,6 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
discardLayoutState = ShouldDiscardLayoutState(httpChannel);
}
- // XXX Bug 1286838: Replace channel owner with loadInfo triggeringPrincipal
- nsCOMPtr<nsISupports> owner;
- aChannel->GetOwner(getter_AddRefs(owner));
- triggeringPrincipal = do_QueryInterface(owner);
-
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
if (loadInfo) {
if (!triggeringPrincipal) {
@@ -12649,10 +12663,6 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
srcdoc = NullString();
}
- // If there is no triggeringPrincipal we can fall back to using the
- // SystemPrincipal as the triggeringPrincipal for loading the history
- // entry, since the history entry can only end up in history if security
- // checks passed in the initial loading phase.
if (!triggeringPrincipal) {
triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
}
@@ -13917,7 +13927,8 @@ public:
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
- bool aIsTrusted);
+ bool aIsTrusted,
+ nsIPrincipal* aTriggeringPrincipal);
NS_IMETHOD Run() override
{
@@ -13933,7 +13944,7 @@ public:
mHandler->OnLinkClickSync(mContent, mURI,
mTargetSpec.get(), mFileName,
mPostDataStream, mHeadersDataStream,
- nullptr, nullptr);
+ nullptr, nullptr, mTriggeringPrincipal);
}
return NS_OK;
}
@@ -13948,6 +13959,7 @@ private:
nsCOMPtr<nsIContent> mContent;
PopupControlState mPopupState;
bool mIsTrusted;
+ nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
};
OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
@@ -13957,7 +13969,8 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
- bool aIsTrusted)
+ bool aIsTrusted,
+ nsIPrincipal* aTriggeringPrincipal)
: mHandler(aHandler)
, mURI(aURI)
, mTargetSpec(aTargetSpec)
@@ -13967,6 +13980,7 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
, mContent(aContent)
, mPopupState(mHandler->mScriptGlobal->GetPopupControlState())
, mIsTrusted(aIsTrusted)
+ , mTriggeringPrincipal(aTriggeringPrincipal)
{
}
@@ -13977,7 +13991,8 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
- bool aIsTrusted)
+ bool aIsTrusted,
+ nsIPrincipal* aTriggeringPrincipal)
{
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
@@ -14016,7 +14031,8 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
nsCOMPtr<nsIRunnable> ev =
new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName,
- aPostDataStream, aHeadersDataStream, aIsTrusted);
+ aPostDataStream, aHeadersDataStream,
+ aIsTrusted, aTriggeringPrincipal);
return NS_DispatchToCurrentThread(ev);
}
@@ -14028,7 +14044,8 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
nsIDocShell** aDocShell,
- nsIRequest** aRequest)
+ nsIRequest** aRequest,
+ nsIPrincipal* aTriggeringPrincipal)
{
// Initialize the DocShell / Request
if (aDocShell) {
@@ -14151,13 +14168,18 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
return NS_ERROR_OUT_OF_MEMORY;
}
+ // if the triggeringPrincipal is not passed explicitly, then we
+ // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
+ nsCOMPtr<nsIPrincipal> triggeringPrincipal =
+ aTriggeringPrincipal ? aTriggeringPrincipal
+ : aContent->NodePrincipal();
+
nsresult rv = InternalLoad(clonedURI, // New URI
nullptr, // Original URI
false, // LoadReplace
referer, // Referer URI
refererPolicy, // Referer policy
- aContent->NodePrincipal(), // Triggering is our node's
- // principal
+ triggeringPrincipal,
aContent->NodePrincipal(),
flags,
target, // Window target
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index 63a4e3358..f510a15b0 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -201,7 +201,8 @@ public:
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
- bool aIsTrusted) override;
+ bool aIsTrusted,
+ nsIPrincipal* aTriggeringPrincipal) override;
NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
nsIURI* aURI,
const char16_t* aTargetSpec,
@@ -209,7 +210,8 @@ public:
nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0,
nsIDocShell** aDocShell = 0,
- nsIRequest** aRequest = 0) override;
+ nsIRequest** aRequest = 0,
+ nsIPrincipal* aTriggeringPrincipal = nullptr) override;
NS_IMETHOD OnOverLink(nsIContent* aContent,
nsIURI* aURI,
const char16_t* aTargetSpec) override;
diff --git a/docshell/base/nsILinkHandler.h b/docshell/base/nsILinkHandler.h
index 7cdcd566d..7069f1f1d 100644
--- a/docshell/base/nsILinkHandler.h
+++ b/docshell/base/nsILinkHandler.h
@@ -37,6 +37,8 @@ public:
* @param aFileName non-null when the link should be downloaded as the given file
* @param aHeadersDataStream ???
* @param aIsTrusted false if the triggerer is an untrusted DOM event.
+ * @param aTriggeringPrincipal, if not passed explicitly we fall back to
+ * the document's principal.
*/
NS_IMETHOD OnLinkClick(nsIContent* aContent,
nsIURI* aURI,
@@ -44,7 +46,8 @@ public:
const nsAString& aFileName,
nsIInputStream* aPostDataStream,
nsIInputStream* aHeadersDataStream,
- bool aIsTrusted) = 0;
+ bool aIsTrusted,
+ nsIPrincipal* aTriggeringPrincipal) = 0;
/**
* Process a click on a link.
@@ -61,6 +64,8 @@ public:
* @param aHeadersDataStream ???
* @param aDocShell (out-param) the DocShell that the request was opened on
* @param aRequest the request that was opened
+ * @param aTriggeringPrincipal, if not passed explicitly we fall back to
+ * the document's principal.
*/
NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
nsIURI* aURI,
@@ -69,7 +74,8 @@ public:
nsIInputStream* aPostDataStream = 0,
nsIInputStream* aHeadersDataStream = 0,
nsIDocShell** aDocShell = 0,
- nsIRequest** aRequest = 0) = 0;
+ nsIRequest** aRequest = 0,
+ nsIPrincipal* aTriggeringPrincipal = nullptr) = 0;
/**
* Process a mouse-over a link.
diff --git a/docshell/base/nsIWebNavigation.idl b/docshell/base/nsIWebNavigation.idl
index 241d0731c..c3e2fc550 100644
--- a/docshell/base/nsIWebNavigation.idl
+++ b/docshell/base/nsIWebNavigation.idl
@@ -9,6 +9,7 @@ interface nsIDOMDocument;
interface nsIInputStream;
interface nsISHistory;
interface nsIURI;
+interface nsIPrincipal;
/**
* The nsIWebNavigation interface defines an interface for navigating the web.
@@ -288,14 +289,20 @@ interface nsIWebNavigation : nsISupports
* that at present this argument is only used with view-source aURIs
* and cannot be used to resolve aURI.
* This parameter is optional and may be null.
- */
- void loadURIWithOptions(in wstring aURI,
- in unsigned long aLoadFlags,
- in nsIURI aReferrer,
- in unsigned long aReferrerPolicy,
- in nsIInputStream aPostData,
- in nsIInputStream aHeaders,
- in nsIURI aBaseURI);
+ * @param aTriggeringPrincipal
+ * The principal that initiated the load of aURI. If omitted docShell
+ * tries to create a codeBasePrincipal from aReferrer if not null. If
+ * aReferrer is also null docShell peforms a load using the
+ * SystemPrincipal as the triggeringPrincipal.
+ */
+ void loadURIWithOptions(in wstring aURI,
+ in unsigned long aLoadFlags,
+ in nsIURI aReferrer,
+ in unsigned long aReferrerPolicy,
+ in nsIInputStream aPostData,
+ in nsIInputStream aHeaders,
+ in nsIURI aBaseURI,
+ [optional] in nsIPrincipal aTriggeringPrincipal);
/**
* Tells the Object to reload the current page. There may be cases where the
diff --git a/docshell/shistory/nsSHEntry.cpp b/docshell/shistory/nsSHEntry.cpp
index 9d972136f..6b0b066d9 100644
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -416,6 +416,9 @@ nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle,
uint64_t aDocShellID,
bool aDynamicCreation)
{
+ MOZ_ASSERT(aTriggeringPrincipal,
+ "need a valid triggeringPrincipal to create a session history entry");
+
mURI = aURI;
mTitle = aTitle;
mPostData = aInputStream;
diff --git a/docshell/shistory/nsSHistory.cpp b/docshell/shistory/nsSHistory.cpp
index 7c148ffcc..9443b92bc 100644
--- a/docshell/shistory/nsSHistory.cpp
+++ b/docshell/shistory/nsSHistory.cpp
@@ -1582,7 +1582,8 @@ nsSHistory::LoadURIWithOptions(const char16_t* aURI,
uint32_t aReferrerPolicy,
nsIInputStream* aPostStream,
nsIInputStream* aExtraHeaderStream,
- nsIURI* aBaseURI)
+ nsIURI* aBaseURI,
+ nsIPrincipal* aTriggeringPrincipal)
{
return NS_OK;
}
diff --git a/docshell/test/browser/browser.ini b/docshell/test/browser/browser.ini
index 9211092a4..300caff1a 100644
--- a/docshell/test/browser/browser.ini
+++ b/docshell/test/browser/browser.ini
@@ -1,5 +1,6 @@
[DEFAULT]
support-files =
+ dummy_page.html
favicon_bug655270.ico
file_bug234628-1-child.html
file_bug234628-1.html
@@ -45,6 +46,7 @@ support-files =
browser_timelineMarkers-frame-05.js
head.js
frame-head.js
+ file_click_link_within_view_source.html
[browser_bug1206879.js]
[browser_bug1309900_crossProcessHistoryNavigation.js]
@@ -91,3 +93,4 @@ skip-if = true # Bug 1220415
[browser_timelineMarkers-04.js]
[browser_timelineMarkers-05.js]
[browser_ua_emulation.js]
+[browser_click_link_within_view_source.js]
diff --git a/docshell/test/browser/browser_click_link_within_view_source.js b/docshell/test/browser/browser_click_link_within_view_source.js
new file mode 100644
index 000000000..84cfc1f0f
--- /dev/null
+++ b/docshell/test/browser/browser_click_link_within_view_source.js
@@ -0,0 +1,60 @@
+"use strict";
+
+/**
+ * Test for Bug 1359204
+ *
+ * Loading a local file, then view-source on that file. Make sure that
+ * clicking a link within that view-source page is not blocked by security checks.
+ */
+
+add_task(function* test_click_link_within_view_source() {
+ let TEST_FILE = "file_click_link_within_view_source.html";
+ let TEST_FILE_URI = getChromeDir(getResolvedURI(gTestPath));
+ TEST_FILE_URI.append(TEST_FILE);
+ TEST_FILE_URI = Services.io.newFileURI(TEST_FILE_URI).spec;
+
+ let DUMMY_FILE = "dummy_page.html";
+ let DUMMY_FILE_URI = getChromeDir(getResolvedURI(gTestPath));
+ DUMMY_FILE_URI.append(DUMMY_FILE);
+ DUMMY_FILE_URI = Services.io.newFileURI(DUMMY_FILE_URI).spec;
+
+ yield BrowserTestUtils.withNewTab(TEST_FILE_URI, function*(aBrowser) {
+ let tabSpec = gBrowser.selectedBrowser.currentURI.spec;
+ info("loading: " + tabSpec);
+ ok(tabSpec.startsWith("file://") && tabSpec.endsWith(TEST_FILE),
+ "sanity check to make sure html loaded");
+
+ info("click view-source of html");
+ let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
+ document.getElementById("View:PageSource").doCommand();
+
+ let tab = yield tabPromise;
+ tabSpec = gBrowser.selectedBrowser.currentURI.spec;
+ info("loading: " + tabSpec);
+ ok(tabSpec.startsWith("view-source:file://") && tabSpec.endsWith(TEST_FILE),
+ "loading view-source of html succeeded");
+
+ info("click testlink within view-source page");
+ let loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, url => url.endsWith("dummy_page.html"));
+ yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function*() {
+ if (content.document.readyState != "complete") {
+ yield ContentTaskUtils.waitForEvent(content.document, "readystatechange", false, () =>
+ content.document.readyState == "complete");
+ }
+ // document.getElementById() does not work on a view-source page, hence we use document.links
+ let linksOnPage = content.document.links;
+ is (linksOnPage.length, 1, "sanity check: make sure only one link is present on page");
+ let myLink = content.document.links[0];
+ myLink.click();
+ });
+
+ yield loadPromise;
+
+ tabSpec = gBrowser.selectedBrowser.currentURI.spec;
+ info("loading: " + tabSpec);
+ ok(tabSpec.startsWith("view-source:file://") && tabSpec.endsWith(DUMMY_FILE),
+ "loading view-source of html succeeded");
+
+ yield BrowserTestUtils.removeTab(tab);
+ });
+});
diff --git a/docshell/test/browser/browser_history_triggeringprincipal_viewsource.js b/docshell/test/browser/browser_history_triggeringprincipal_viewsource.js
new file mode 100644
index 000000000..96908bbc2
--- /dev/null
+++ b/docshell/test/browser/browser_history_triggeringprincipal_viewsource.js
@@ -0,0 +1,50 @@
+"use strict";
+
+const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
+const HTML_URI = TEST_PATH + "dummy_page.html";
+const VIEW_SRC_URI = "view-source:" + HTML_URI;
+
+add_task(function*() {
+ info("load baseline html in new tab");
+ yield BrowserTestUtils.withNewTab(HTML_URI, function*(aBrowser) {
+ is(gBrowser.selectedBrowser.currentURI.spec, HTML_URI,
+ "sanity check to make sure html loaded");
+
+ info("right-click -> view-source of html");
+ let vSrcCtxtMenu = document.getElementById("contentAreaContextMenu");
+ let popupPromise = BrowserTestUtils.waitForEvent(vSrcCtxtMenu, "popupshown");
+ BrowserTestUtils.synthesizeMouseAtCenter("body", { type: "contextmenu", button: 2 }, aBrowser);
+ yield popupPromise;
+ let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, VIEW_SRC_URI);
+ let vSrcItem = vSrcCtxtMenu.getElementsByAttribute("id", "context-viewsource")[0];
+ vSrcItem.click();
+ vSrcCtxtMenu.hidePopup();
+ let tab = yield tabPromise;
+ is(gBrowser.selectedBrowser.currentURI.spec, VIEW_SRC_URI,
+ "loading view-source of html succeeded");
+
+ info ("load html file again before going .back()");
+ let loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, HTML_URI);
+ yield ContentTask.spawn(tab.linkedBrowser, HTML_URI, HTML_URI => {
+ content.document.location = HTML_URI;
+ });
+ yield loadPromise;
+ is(gBrowser.selectedBrowser.currentURI.spec, HTML_URI,
+ "loading html another time succeeded");
+
+ info("click .back() to view-source of html again and make sure the history entry has a triggeringPrincipal");
+ let backCtxtMenu = document.getElementById("contentAreaContextMenu");
+ popupPromise = BrowserTestUtils.waitForEvent(backCtxtMenu, "popupshown");
+ BrowserTestUtils.synthesizeMouseAtCenter("body", { type: "contextmenu", button: 2 }, aBrowser);
+ yield popupPromise;
+ loadPromise = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, VIEW_SRC_URI);
+ let backItem = backCtxtMenu.getElementsByAttribute("id", "context-back")[0];
+ backItem.click();
+ backCtxtMenu.hidePopup();
+ yield loadPromise;
+ is(gBrowser.selectedBrowser.currentURI.spec, VIEW_SRC_URI,
+ "clicking .back() to view-source of html succeeded");
+
+ yield BrowserTestUtils.removeTab(tab);
+ });
+});
diff --git a/docshell/test/browser/dummy_page.html b/docshell/test/browser/dummy_page.html
new file mode 100644
index 000000000..59bf2a5f8
--- /dev/null
+++ b/docshell/test/browser/dummy_page.html
@@ -0,0 +1,6 @@
+<html>
+<head> <meta charset="utf-8"> </head>
+ <body>
+ just a dummy html file
+ </body>
+</html>
diff --git a/docshell/test/browser/file_click_link_within_view_source.html b/docshell/test/browser/file_click_link_within_view_source.html
new file mode 100644
index 000000000..d78e4ba0f
--- /dev/null
+++ b/docshell/test/browser/file_click_link_within_view_source.html
@@ -0,0 +1,6 @@
+<html>
+<head> <meta charset="utf-8"> </head>
+ <body>
+ <a id="testlink" href="dummy_page.html">clickme</a>
+ </body>
+</html>
diff --git a/docshell/test/dummy_page.html b/docshell/test/dummy_page.html
new file mode 100644
index 000000000..59bf2a5f8
--- /dev/null
+++ b/docshell/test/dummy_page.html
@@ -0,0 +1,6 @@
+<html>
+<head> <meta charset="utf-8"> </head>
+ <body>
+ just a dummy html file
+ </body>
+</html>
diff --git a/docshell/test/mochitest.ini b/docshell/test/mochitest.ini
index 7b27908fb..2298bed74 100644
--- a/docshell/test/mochitest.ini
+++ b/docshell/test/mochitest.ini
@@ -11,6 +11,7 @@ support-files =
bug668513_redirect.html
bug668513_redirect.html^headers^
bug691547_frame.html
+ dummy_page.html
file_anchor_scroll_after_document_open.html
file_bug385434_1.html
file_bug385434_2.html
@@ -94,3 +95,4 @@ skip-if = toolkit == 'android' # bug 784321
support-files = file_framedhistoryframes.html
[test_pushState_after_document_open.html]
[test_windowedhistoryframes.html]
+[test_triggeringprincipal_location_seturi.html]
diff --git a/docshell/test/test_triggeringprincipal_location_seturi.html b/docshell/test/test_triggeringprincipal_location_seturi.html
new file mode 100644
index 000000000..3b0c7bac5
--- /dev/null
+++ b/docshell/test/test_triggeringprincipal_location_seturi.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<script type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+const SAME_ORIGIN_URI = "http://mochi.test:8888/tests/docshell/test/dummy_page.html";
+const CROSS_ORIGIN_URI = "http://example.com/tests/docshell/test/dummy_page.html";
+const NUMBER_OF_TESTS = 3;
+let testCounter = 0;
+
+function checkFinish() {
+ testCounter++;
+ if (testCounter < NUMBER_OF_TESTS) {
+ return;
+ }
+ SimpleTest.finish();
+}
+
+// ---- test 1 ----
+
+let myFrame1 = document.createElement("iframe");
+myFrame1.src = SAME_ORIGIN_URI;
+myFrame1.addEventListener("load", checkLoadFrame1);
+document.documentElement.appendChild(myFrame1);
+
+function checkLoadFrame1() {
+ myFrame1.removeEventListener('load', checkLoadFrame1, false);
+ // window.location.href is no longer cross-origin accessible in gecko.
+ is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, SAME_ORIGIN_URI,
+ "initial same origin dummy loaded into frame1");
+
+ SpecialPowers.wrap(myFrame1.contentWindow).location.hash = "#bar";
+ is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, SAME_ORIGIN_URI + "#bar",
+ "initial same origin dummy#bar loaded into iframe1");
+
+ myFrame1.addEventListener("load", checkNavFrame1);
+ myFrame1.src = CROSS_ORIGIN_URI;
+}
+
+function checkNavFrame1() {
+ myFrame1.removeEventListener('load', checkNavFrame1, false);
+ is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, CROSS_ORIGIN_URI,
+ "cross origin dummy loaded into frame1");
+
+ myFrame1.addEventListener("load", checkBackNavFrame1);
+ myFrame1.src = SAME_ORIGIN_URI + "#bar";
+}
+
+function checkBackNavFrame1() {
+ myFrame1.removeEventListener('load', checkBackNavFrame1, false);
+ is(SpecialPowers.wrap(myFrame1.contentWindow).location.href, SAME_ORIGIN_URI + "#bar",
+ "navagiating back to same origin dummy for frame1");
+ checkFinish();
+}
+
+// ---- test 2 ----
+
+let myFrame2 = document.createElement("iframe");
+myFrame2.src = "about:blank";
+myFrame2.addEventListener("load", checkLoadFrame2);
+document.documentElement.appendChild(myFrame2);
+
+function checkLoadFrame2() {
+ myFrame2.removeEventListener('load', checkLoadFrame2, false);
+ is(SpecialPowers.wrap(myFrame2.contentWindow).location.href, "about:blank",
+ "initial about:blank frame loaded");
+
+ myFrame2.contentWindow.location.hash = "#foo";
+ is(SpecialPowers.wrap(myFrame2.contentWindow).location.href, "about:blank#foo",
+ "about:blank#foo frame loaded");
+
+ myFrame2.addEventListener('load', checkHistoryFrame2);
+ myFrame2.src = "about:blank";
+}
+
+function checkHistoryFrame2() {
+ myFrame2.removeEventListener('load', checkHistoryFrame2, false);
+ is(SpecialPowers.wrap(myFrame2.contentWindow).location.href, "about:blank",
+ "about:blank frame loaded again");
+ checkFinish();
+}
+
+// ---- test 3 ----
+
+let myFrame3 = document.createElement("frame");
+document.documentElement.appendChild(myFrame3);
+myFrame3.contentWindow.location.hash = "#foo";
+
+is(myFrame3.contentWindow.location.href, "about:blank#foo",
+ "created history entry with about:blank#foo");
+checkFinish();
+
+</script>
+</body>
+</html>