diff --git a/browser/components/privatebrowsing/test/browser/browser.ini b/browser/components/privatebrowsing/test/browser/browser.ini
index 8b16c8b8432f..bbf7e5693c25 100644
--- a/browser/components/privatebrowsing/test/browser/browser.ini
+++ b/browser/components/privatebrowsing/test/browser/browser.ini
@@ -13,6 +13,7 @@ support-files =
head.js
popup.html
title.sjs
+ empty_file.html
[browser_privatebrowsing_DownloadLastDirWithCPS.js]
[browser_privatebrowsing_about.js]
@@ -45,3 +46,4 @@ tags = trackingprotection
[browser_privatebrowsing_zoom.js]
[browser_privatebrowsing_zoomrestore.js]
[browser_privatebrowsing_newtab_from_popup.js]
+[browser_privatebrowsing_blobUrl.js]
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_blobUrl.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_blobUrl.js
new file mode 100644
index 000000000000..7b2d26209e97
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_blobUrl.js
@@ -0,0 +1,47 @@
+"use strict";
+
+// Here we want to test that blob URLs are not available between private and
+// non-private browsing.
+
+const BASE_URI = "http://mochi.test:8888/browser/browser/components/"
+ + "privatebrowsing/test/browser/empty_file.html";
+
+add_task(function* test() {
+ info("Creating a normal window...");
+ let win = yield BrowserTestUtils.openNewBrowserWindow();
+ let tab = win.gBrowser.selectedBrowser;
+ tab.loadURI(BASE_URI);
+ yield BrowserTestUtils.browserLoaded(tab);
+
+ let blobURL;
+
+ info("Creating a blob URL...");
+ yield ContentTask.spawn(tab, null, function() {
+ return Promise.resolve(content.window.URL.createObjectURL(new content.window.Blob([123])));
+ }).then(newURL => { blobURL = newURL });
+
+ info("Blob URL: " + blobURL);
+
+ info("Creating a private window...");
+ let privateWin = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+ let privateTab = privateWin.gBrowser.selectedBrowser;
+ privateTab.loadURI(BASE_URI);
+ yield BrowserTestUtils.browserLoaded(privateTab);
+
+ yield ContentTask.spawn(privateTab, blobURL, function(url) {
+ return new Promise(resolve => {
+ var xhr = new content.window.XMLHttpRequest();
+ try {
+ xhr.open("GET", url);
+ resolve("OpenSucceeded");
+ } catch(e) {
+ resolve("OpenThrew");
+ }
+ });
+ }).then(status => {
+ is(status, "OpenThrew", "Using a blob URI from one user context id in another should not work");
+ });
+
+ yield BrowserTestUtils.closeWindow(win);
+ yield BrowserTestUtils.closeWindow(privateWin);
+});
diff --git a/browser/components/privatebrowsing/test/browser/empty_file.html b/browser/components/privatebrowsing/test/browser/empty_file.html
new file mode 100644
index 000000000000..0dc101b53359
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/empty_file.html
@@ -0,0 +1 @@
+
diff --git a/dom/base/URL.cpp b/dom/base/URL.cpp
index 654995fee03d..d48ceb219baf 100644
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -129,16 +129,28 @@ void
URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
const objectURLOptions& aOptions,
nsAString& aResult,
- ErrorResult& aError)
+ ErrorResult& aRv)
{
- nsCOMPtr principal = nsContentUtils::ObjectPrincipal(aGlobal.Get());
+ nsCOMPtr principal =
+ nsContentUtils::ObjectPrincipal(aGlobal.Get());
+ if (NS_WARN_IF(!principal)) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return;
+ }
+
+ nsCOMPtr window =
+ do_QueryInterface(aGlobal.GetAsSupports());
+ if (NS_WARN_IF(!window)) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return;
+ }
nsCString url;
- nsresult rv = nsHostObjectProtocolHandler::
+ aRv = nsHostObjectProtocolHandler::
AddDataEntry(NS_LITERAL_CSTRING(MEDIASOURCEURI_SCHEME),
- &aSource, principal, url);
- if (NS_FAILED(rv)) {
- aError.Throw(rv);
+ &aSource, principal,
+ nsGlobalWindow::Cast(window)->IsPrivateBrowsing(), url);
+ if (NS_WARN_IF(aRv.Failed())) {
return;
}
@@ -166,11 +178,18 @@ URL::CreateObjectURLInternal(const GlobalObject& aGlobal, nsISupports* aObject,
nsCOMPtr principal = nsContentUtils::ObjectPrincipal(aGlobal.Get());
+ nsCOMPtr window =
+ do_QueryInterface(aGlobal.GetAsSupports());
+ if (NS_WARN_IF(!window)) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return;
+ }
+
nsAutoCString url;
- nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(aScheme, aObject,
- principal, url);
- if (NS_FAILED(rv)) {
- aRv.Throw(rv);
+ aRv = nsHostObjectProtocolHandler::
+ AddDataEntry(aScheme, aObject, principal,
+ nsGlobalWindow::Cast(window)->IsPrivateBrowsing(), url);
+ if (NS_WARN_IF(aRv.Failed())) {
return;
}
diff --git a/dom/base/nsHostObjectProtocolHandler.cpp b/dom/base/nsHostObjectProtocolHandler.cpp
index d8f2326e2e46..5ef736074b75 100644
--- a/dom/base/nsHostObjectProtocolHandler.cpp
+++ b/dom/base/nsHostObjectProtocolHandler.cpp
@@ -32,6 +32,7 @@ struct DataInfo
// mObject is expected to be an nsIDOMBlob, DOMMediaStream, or MediaSource
nsCOMPtr mObject;
nsCOMPtr mPrincipal;
+ bool mPrivateBrowsing;
nsCString mStack;
};
@@ -321,6 +322,7 @@ nsresult
nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
nsISupports* aObject,
nsIPrincipal* aPrincipal,
+ bool aPrivateBrowsing,
nsACString& aUri)
{
Init();
@@ -336,6 +338,7 @@ nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
info->mObject = aObject;
info->mPrincipal = aPrincipal;
+ info->mPrivateBrowsing = aPrivateBrowsing;
mozilla::BlobURLsReporter::GetJSStackForBlob(info);
gDataTable->Put(aUri, info);
@@ -537,6 +540,17 @@ nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri,
return NS_ERROR_DOM_BAD_URI;
}
+ bool usePrivateBrowsing = false;
+ ErrorResult rv;
+ rv = aLoadInfo->GetUsePrivateBrowsing(&usePrivateBrowsing);
+ if (NS_WARN_IF(rv.Failed())) {
+ return rv.StealNSResult();
+ }
+
+ if (info->mPrivateBrowsing != usePrivateBrowsing) {
+ return NS_ERROR_DOM_BAD_URI;
+ }
+
nsCOMPtr blob = do_QueryInterface(info->mObject);
if (!blob) {
return NS_ERROR_DOM_BAD_URI;
@@ -551,7 +565,6 @@ nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri,
}
#endif
- ErrorResult rv;
nsCOMPtr stream;
blob->GetInternalStream(getter_AddRefs(stream), rv);
if (NS_WARN_IF(rv.Failed())) {
diff --git a/dom/base/nsHostObjectProtocolHandler.h b/dom/base/nsHostObjectProtocolHandler.h
index d38a93a34d3d..79983b27d51d 100644
--- a/dom/base/nsHostObjectProtocolHandler.h
+++ b/dom/base/nsHostObjectProtocolHandler.h
@@ -54,6 +54,7 @@ public:
static nsresult AddDataEntry(const nsACString& aScheme,
nsISupports* aObject,
nsIPrincipal* aPrincipal,
+ bool aIsPrivateBrowsing,
nsACString& aUri);
static void RemoveDataEntry(const nsACString& aUri);
static nsIPrincipal* GetDataEntryPrincipal(const nsACString& aUri);
diff --git a/dom/workers/URL.cpp b/dom/workers/URL.cpp
index 8c2b05f206fd..60666b25b989 100644
--- a/dom/workers/URL.cpp
+++ b/dom/workers/URL.cpp
@@ -129,7 +129,7 @@ public:
nsAutoCString url;
nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(
NS_LITERAL_CSTRING(BLOBURI_SCHEME),
- mBlobImpl, principal, url);
+ mBlobImpl, principal, mWorkerPrivate->IsInPrivateBrowsing(), url);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to add data entry for the blob!");