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!");