From 2e26b7957b8a2734c460bb7c882ad4906d9e01e3 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 26 Jun 2015 11:18:18 -0700 Subject: [PATCH] Bug 1177621 - SharedWorkers should not be shared between a private and a non-private documents, r=nsm --- docshell/base/nsDocShell.cpp | 5 + dom/base/nsContentUtils.cpp | 31 +++-- dom/base/nsContentUtils.h | 6 + dom/webidl/Navigator.webidl | 2 +- dom/webidl/ServiceWorkerContainer.webidl | 2 +- dom/workers/RuntimeService.cpp | 17 ++- dom/workers/ServiceWorkerContainer.cpp | 20 ++++ dom/workers/ServiceWorkerContainer.h | 2 + dom/workers/ServiceWorkerManager.cpp | 4 +- dom/workers/WorkerPrivate.cpp | 6 + dom/workers/WorkerPrivate.h | 6 + dom/workers/Workers.h | 1 + dom/workers/test/chrome.ini | 3 + dom/workers/test/serviceworkers/chrome.ini | 1 + .../serviceworkers/test_privateBrowsing.html | 93 +++++++++++++++ .../test/sharedWorker_privateBrowsing.js | 5 + .../test_sharedWorker_privateBrowsing.html | 106 ++++++++++++++++++ 17 files changed, 291 insertions(+), 19 deletions(-) create mode 100644 dom/workers/test/serviceworkers/test_privateBrowsing.html create mode 100644 dom/workers/test/sharedWorker_privateBrowsing.js create mode 100644 dom/workers/test/test_sharedWorker_privateBrowsing.html diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 5eba509397c..05894f8465f 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -14027,6 +14027,11 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate, return NS_OK; } + // No in private browsing + if (mInPrivateBrowsing) { + return NS_OK; + } + if (mSandboxFlags) { // If we're sandboxed, don't intercept. return NS_OK; diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index c5f50a269af..96d944f8d82 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -2989,18 +2989,29 @@ nsContentUtils::IsInPrivateBrowsing(nsIDocument* aDoc) if (!aDoc) { return false; } - bool isPrivate = false; + nsCOMPtr loadGroup = aDoc->GetDocumentLoadGroup(); - nsCOMPtr callbacks; if (loadGroup) { - loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); - if (callbacks) { - nsCOMPtr loadContext = do_GetInterface(callbacks); - isPrivate = loadContext && loadContext->UsePrivateBrowsing(); - } - } else { - nsCOMPtr channel = aDoc->GetChannel(); - isPrivate = channel && NS_UsePrivateBrowsing(channel); + return IsInPrivateBrowsing(loadGroup); + } + + nsCOMPtr channel = aDoc->GetChannel(); + return channel && NS_UsePrivateBrowsing(channel); +} + +// static +bool +nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) +{ + if (!aLoadGroup) { + return false; + } + bool isPrivate = false; + nsCOMPtr callbacks; + aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks)); + if (callbacks) { + nsCOMPtr loadContext = do_GetInterface(callbacks); + isPrivate = loadContext && loadContext->UsePrivateBrowsing(); } return isPrivate; } diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index c653af3bb1a..437711af10c 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -69,6 +69,7 @@ class nsIImageLoadingContent; class nsIInterfaceRequestor; class nsIIOService; class nsILineBreaker; +class nsILoadGroup; class nsIMessageBroadcaster; class nsNameSpaceManager; class nsIObserver; @@ -730,6 +731,11 @@ public: */ static bool IsInPrivateBrowsing(nsIDocument* aDoc); + /** + * Returns true if this loadGroup uses Private Browsing. + */ + static bool IsInPrivateBrowsing(nsILoadGroup* aLoadGroup); + /** * If aNode is not an element, return true exactly when aContent's binding * parent is null. diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 11d41501ce2..599d320be0c 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -405,7 +405,7 @@ partial interface Navigator { // Service Workers/Navigation Controllers partial interface Navigator { - [Pref="dom.serviceWorkers.enabled"] + [Func="ServiceWorkerContainer::IsEnabled"] readonly attribute ServiceWorkerContainer serviceWorker; }; diff --git a/dom/webidl/ServiceWorkerContainer.webidl b/dom/webidl/ServiceWorkerContainer.webidl index a28badf2f83..080896f02ab 100644 --- a/dom/webidl/ServiceWorkerContainer.webidl +++ b/dom/webidl/ServiceWorkerContainer.webidl @@ -8,7 +8,7 @@ * */ -[Pref="dom.serviceWorkers.enabled", +[Func="ServiceWorkerContainer::IsEnabled", Exposed=Window] interface ServiceWorkerContainer : EventTarget { // FIXME(nsm): diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index f0d55d67307..df649ab48d5 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -276,7 +276,7 @@ GetWorkerPref(const nsACString& aPref, void GenerateSharedWorkerKey(const nsACString& aScriptSpec, const nsACString& aName, const nsACString& aCacheName, WorkerType aWorkerType, - nsCString& aKey) + bool aPrivateBrowsing, nsCString& aKey) { aKey.Truncate(); NS_NAMED_LITERAL_CSTRING(sharedPrefix, "shared|"); @@ -286,10 +286,12 @@ GenerateSharedWorkerKey(const nsACString& aScriptSpec, const nsACString& aName, aWorkerType == WorkerTypeService); MOZ_ASSERT_IF(aWorkerType == WorkerTypeShared, aCacheName.IsEmpty()); MOZ_ASSERT_IF(aWorkerType == WorkerTypeService, !aCacheName.IsEmpty()); + MOZ_ASSERT_IF(aWorkerType == WorkerTypeService, !aPrivateBrowsing); aKey.SetCapacity(servicePrefix.Length() + aScriptSpec.Length() + - aName.Length() + aCacheName.Length() + 1); + aName.Length() + aCacheName.Length() + 3); aKey.Append(aWorkerType == WorkerTypeService ? servicePrefix : sharedPrefix); + aKey.Append(aPrivateBrowsing ? "1|" : "0|"); nsACString::const_iterator start, end; aName.BeginReading(start); @@ -1517,7 +1519,8 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate) nsAutoCString key; GenerateSharedWorkerKey(sharedWorkerScriptSpec, sharedWorkerName, - cacheName, aWorkerPrivate->Type(), key); + cacheName, aWorkerPrivate->Type(), + aWorkerPrivate->IsInPrivateBrowsing(), key); MOZ_ASSERT(!domainInfo->mSharedWorkerInfos.Get(key)); SharedWorkerInfo* sharedWorkerInfo = @@ -1631,7 +1634,8 @@ RuntimeService::UnregisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate) EmptyCString(); GenerateSharedWorkerKey(match.mSharedWorkerInfo->mScriptSpec, match.mSharedWorkerInfo->mName, - cacheName, aWorkerPrivate->Type(), key); + cacheName, aWorkerPrivate->Type(), + aWorkerPrivate->IsInPrivateBrowsing(), key); domainInfo->mSharedWorkerInfos.Remove(key); } } @@ -2387,7 +2391,7 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx, nsAutoCString key; GenerateSharedWorkerKey(scriptSpec, aName, NS_ConvertUTF16toUTF8(aLoadInfo->mServiceWorkerCacheName), - aType, key); + aType, aLoadInfo->mPrivateBrowsing, key); if (mDomainMap.Get(aLoadInfo->mDomain, &domainInfo) && domainInfo->mSharedWorkerInfos.Get(key, &sharedWorkerInfo)) { @@ -2467,7 +2471,8 @@ RuntimeService::ForgetSharedWorker(WorkerPrivate* aWorkerPrivate) EmptyCString(); GenerateSharedWorkerKey(match.mSharedWorkerInfo->mScriptSpec, match.mSharedWorkerInfo->mName, - cacheName, aWorkerPrivate->Type(), key); + cacheName, aWorkerPrivate->Type(), + aWorkerPrivate->IsInPrivateBrowsing(), key); domainInfo->mSharedWorkerInfos.Remove(key); } } diff --git a/dom/workers/ServiceWorkerContainer.cpp b/dom/workers/ServiceWorkerContainer.cpp index 6491233fa7e..3b614293adb 100644 --- a/dom/workers/ServiceWorkerContainer.cpp +++ b/dom/workers/ServiceWorkerContainer.cpp @@ -15,6 +15,7 @@ #include "nsCycleCollectionParticipant.h" #include "nsServiceManagerUtils.h" +#include "mozilla/dom/Navigator.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ServiceWorkerContainerBinding.h" #include "mozilla/dom/workers/bindings/ServiceWorker.h" @@ -33,6 +34,25 @@ NS_IMPL_RELEASE_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerContainer, DOMEventTargetHelper, mControllerWorker, mReadyPromise) +/* static */ bool +ServiceWorkerContainer::IsEnabled(JSContext* aCx, JSObject* aGlobal) +{ + MOZ_ASSERT(NS_IsMainThread()); + + JS::Rooted global(aCx, aGlobal); + nsCOMPtr window = Navigator::GetWindowFromGlobal(global); + if (!window) { + return false; + } + + nsIDocument* doc = window->GetExtantDoc(); + if (!doc || nsContentUtils::IsInPrivateBrowsing(doc)) { + return false; + } + + return Preferences::GetBool("dom.serviceWorkers.enabled", false); +} + ServiceWorkerContainer::ServiceWorkerContainer(nsPIDOMWindow* aWindow) : DOMEventTargetHelper(aWindow) { diff --git a/dom/workers/ServiceWorkerContainer.h b/dom/workers/ServiceWorkerContainer.h index 56a82181d60..9d0cb105416 100644 --- a/dom/workers/ServiceWorkerContainer.h +++ b/dom/workers/ServiceWorkerContainer.h @@ -33,6 +33,8 @@ public: IMPL_EVENT_HANDLER(error) IMPL_EVENT_HANDLER(message) + static bool IsEnabled(JSContext* aCx, JSObject* aGlobal); + explicit ServiceWorkerContainer(nsPIDOMWindow* aWindow); virtual JSObject* diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 222f1e61958..50eaf107609 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -3612,7 +3612,7 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut bool ServiceWorkerManager::IsAvailable(const OriginAttributes& aOriginAttributes, - nsIURI* aURI) + nsIURI* aURI) { MOZ_ASSERT(aURI); @@ -3625,6 +3625,7 @@ bool ServiceWorkerManager::IsControlled(nsIDocument* aDoc, ErrorResult& aRv) { MOZ_ASSERT(aDoc); + MOZ_ASSERT(!nsContentUtils::IsInPrivateBrowsing(aDoc)); nsRefPtr registration; nsresult rv = GetDocumentRegistration(aDoc, getter_AddRefs(registration)); @@ -3747,6 +3748,7 @@ ServiceWorkerManager::CreateServiceWorker(nsIPrincipal* aPrincipal, info.mIndexedDBAllowed = indexedDB::IDBFactory::AllowedForPrincipal(aPrincipal); + info.mPrivateBrowsing = false; nsCOMPtr csp; rv = aPrincipal->GetCsp(getter_AddRefs(csp)); diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 43eac9e7b54..437d7fbe5c8 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -2336,6 +2336,7 @@ WorkerLoadInfo::WorkerLoadInfo() , mIsInPrivilegedApp(false) , mIsInCertifiedApp(false) , mIndexedDBAllowed(false) + , mPrivateBrowsing(true) { MOZ_COUNT_CTOR(WorkerLoadInfo); } @@ -2390,6 +2391,7 @@ WorkerLoadInfo::StealFrom(WorkerLoadInfo& aOther) mIsInPrivilegedApp = aOther.mIsInPrivilegedApp; mIsInCertifiedApp = aOther.mIsInCertifiedApp; mIndexedDBAllowed = aOther.mIndexedDBAllowed; + mPrivateBrowsing = aOther.mPrivateBrowsing; } template @@ -4163,6 +4165,7 @@ WorkerPrivateParent::SetPrincipal(nsIPrincipal* aPrincipal, mLoadInfo.mLoadGroup = aLoadGroup; mLoadInfo.mPrincipalInfo = new PrincipalInfo(); + mLoadInfo.mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(aLoadGroup); MOZ_ALWAYS_TRUE(NS_SUCCEEDED( PrincipalToPrincipalInfo(aPrincipal, mLoadInfo.mPrincipalInfo))); @@ -4964,6 +4967,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow, loadInfo.mFromWindow = aParent->IsFromWindow(); loadInfo.mWindowID = aParent->WindowID(); loadInfo.mIndexedDBAllowed = aParent->IsIndexedDBAllowed(); + loadInfo.mPrivateBrowsing = aParent->IsInPrivateBrowsing(); } else { AssertIsOnMainThread(); @@ -5083,6 +5087,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow, loadInfo.mFromWindow = true; loadInfo.mWindowID = globalWindow->WindowID(); loadInfo.mIndexedDBAllowed = IDBFactory::AllowedForWindow(globalWindow); + loadInfo.mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(document); } else { // Not a window MOZ_ASSERT(isChrome); @@ -5124,6 +5129,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindow* aWindow, loadInfo.mFromWindow = false; loadInfo.mWindowID = UINT64_MAX; loadInfo.mIndexedDBAllowed = true; + loadInfo.mPrivateBrowsing = false; } MOZ_ASSERT(loadInfo.mPrincipal); diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index d644df811d9..ffcd8003246 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -753,6 +753,12 @@ public: return mLoadInfo.mIndexedDBAllowed; } + bool + IsInPrivateBrowsing() const + { + return mLoadInfo.mPrivateBrowsing; + } + void GetAllSharedWorkers(nsTArray>& aSharedWorkers); diff --git a/dom/workers/Workers.h b/dom/workers/Workers.h index 60fa2a1996a..b777eaa2227 100644 --- a/dom/workers/Workers.h +++ b/dom/workers/Workers.h @@ -259,6 +259,7 @@ struct WorkerLoadInfo bool mIsInPrivilegedApp; bool mIsInCertifiedApp; bool mIndexedDBAllowed; + bool mPrivateBrowsing; WorkerLoadInfo(); ~WorkerLoadInfo(); diff --git a/dom/workers/test/chrome.ini b/dom/workers/test/chrome.ini index 40209252a8e..876e5b5037d 100644 --- a/dom/workers/test/chrome.ini +++ b/dom/workers/test/chrome.ini @@ -48,6 +48,8 @@ support-files = workersDisabled_worker.js file_url.jsm bug1062920_worker.js + empty.html + sharedWorker_privateBrowsing.js [test_WorkerDebugger.xul] [test_WorkerDebugger.initialize.xul] @@ -76,3 +78,4 @@ support-files = [test_workersDisabled.xul] [test_url.xul] [test_bug1062920.xul] +[test_sharedWorker_privateBrowsing.html] diff --git a/dom/workers/test/serviceworkers/chrome.ini b/dom/workers/test/serviceworkers/chrome.ini index cb1b272ccc0..42a89527496 100644 --- a/dom/workers/test/serviceworkers/chrome.ini +++ b/dom/workers/test/serviceworkers/chrome.ini @@ -4,3 +4,4 @@ support-files = app/* [test_app_installation.html] +[test_privateBrowsing.html] diff --git a/dom/workers/test/serviceworkers/test_privateBrowsing.html b/dom/workers/test/serviceworkers/test_privateBrowsing.html new file mode 100644 index 00000000000..0a75bf3cf47 --- /dev/null +++ b/dom/workers/test/serviceworkers/test_privateBrowsing.html @@ -0,0 +1,93 @@ + + + Test for ServiceWorker - Private Browsing + + + + + + + + diff --git a/dom/workers/test/sharedWorker_privateBrowsing.js b/dom/workers/test/sharedWorker_privateBrowsing.js new file mode 100644 index 00000000000..9d7ec886fb2 --- /dev/null +++ b/dom/workers/test/sharedWorker_privateBrowsing.js @@ -0,0 +1,5 @@ +var counter = 0; +onconnect = function(evt) { + evt.ports[0].postMessage(++counter); +} + diff --git a/dom/workers/test/test_sharedWorker_privateBrowsing.html b/dom/workers/test/test_sharedWorker_privateBrowsing.html new file mode 100644 index 00000000000..5ae8ae4e345 --- /dev/null +++ b/dom/workers/test/test_sharedWorker_privateBrowsing.html @@ -0,0 +1,106 @@ + + + Test for SharedWorker - Private Browsing + + + + + + + +