author | Fernando Jimenez <ferjmoreno@gmail.com> |
Thu, 11 Jun 2015 19:42:38 +0200 | |
changeset 248372 | 82951c8ba8c53a3d7b1707bdff3508594e8391a3 |
parent 248371 | e986f0bc71c5dcc73a0a2779f77d8543a4029382 |
child 248373 | 3257bc1b54987843b019009412bf7ea6722dfecb |
push id | 28893 |
push user | kwierso@gmail.com |
push date | Fri, 12 Jun 2015 00:02:58 +0000 |
treeherder | autoland@8cf9d3e497f9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | baku |
bugs | 1169249 |
milestone | 41.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/workers/ServiceWorkerManager.cpp | file | annotate | diff | comparison | revisions | |
dom/workers/ServiceWorkerManager.h | file | annotate | diff | comparison | revisions |
--- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -1,16 +1,18 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ServiceWorkerManager.h" +#include "mozIApplication.h" +#include "mozIApplicationClearPrivateDataParams.h" #include "nsIAppsService.h" #include "nsIDOMEventTarget.h" #include "nsIDocument.h" #include "nsIScriptSecurityManager.h" #include "nsIStreamLoader.h" #include "nsIHttpChannel.h" #include "nsIHttpChannelInternal.h" #include "nsIHttpHeaderVisitor.h" @@ -73,16 +75,17 @@ using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::ipc; BEGIN_WORKERS_NAMESPACE #define PURGE_DOMAIN_DATA "browser:purge-domain-data" #define PURGE_SESSION_HISTORY "browser:purge-session-history" +#define WEBAPPS_CLEAR_DATA "webapps-clear-data" static_assert(nsIHttpChannelInternal::CORS_MODE_SAME_ORIGIN == static_cast<uint32_t>(RequestMode::Same_origin), "RequestMode enumeration value should match Necko CORS mode value."); static_assert(nsIHttpChannelInternal::CORS_MODE_NO_CORS == static_cast<uint32_t>(RequestMode::No_cors), "RequestMode enumeration value should match Necko CORS mode value."); static_assert(nsIHttpChannelInternal::CORS_MODE_CORS == static_cast<uint32_t>(RequestMode::Cors), "RequestMode enumeration value should match Necko CORS mode value."); static_assert(nsIHttpChannelInternal::CORS_MODE_CORS_WITH_FORCED_PREFLIGHT == static_cast<uint32_t>(RequestMode::Cors_with_forced_preflight), @@ -410,16 +413,18 @@ ServiceWorkerManager::Init() if (obs) { DebugOnly<nsresult> rv; rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false /* ownsWeak */); MOZ_ASSERT(NS_SUCCEEDED(rv)); rv = obs->AddObserver(this, PURGE_SESSION_HISTORY, false /* ownsWeak */); MOZ_ASSERT(NS_SUCCEEDED(rv)); rv = obs->AddObserver(this, PURGE_DOMAIN_DATA, false /* ownsWeak */); MOZ_ASSERT(NS_SUCCEEDED(rv)); + rv = obs->AddObserver(this, WEBAPPS_CLEAR_DATA, false /* ownsWeak */); + MOZ_ASSERT(NS_SUCCEEDED(rv)); } } } class ContinueLifecycleTask : public nsISupports { NS_DECL_ISUPPORTS @@ -4027,37 +4032,37 @@ HasRootDomain(nsIURI* aURI, const nsACSt // Equals failed so this is fine. return false; } char prevChar = *(--start); return prevChar == '.'; } -struct UnregisterIfMatchesHostData +struct UnregisterIfMatchesHostOrPrincipalData { - UnregisterIfMatchesHostData( + UnregisterIfMatchesHostOrPrincipalData( ServiceWorkerManager::RegistrationDataPerPrincipal* aRegistrationData, void* aUserData) : mRegistrationData(aRegistrationData) , mUserData(aUserData) {} ServiceWorkerManager::RegistrationDataPerPrincipal* mRegistrationData; void *mUserData; }; // If host/aData is null, unconditionally unregisters. PLDHashOperator UnregisterIfMatchesHost(const nsACString& aScope, ServiceWorkerRegistrationInfo* aReg, void* aPtr) { - UnregisterIfMatchesHostData* data = - static_cast<UnregisterIfMatchesHostData*>(aPtr); + UnregisterIfMatchesHostOrPrincipalData* data = + static_cast<UnregisterIfMatchesHostOrPrincipalData*>(aPtr); // We avoid setting toRemove = aReg by default since there is a possibility // of failure when data->mUserData is passed, in which case we don't want to // remove the registration. ServiceWorkerRegistrationInfo* toRemove = nullptr; if (data->mUserData) { const nsACString& domain = *static_cast<nsACString*>(data->mUserData); nsCOMPtr<nsIURI> scopeURI; @@ -4079,22 +4084,58 @@ UnregisterIfMatchesHost(const nsACString } // If host/aData is null, unconditionally unregisters. PLDHashOperator UnregisterIfMatchesHostPerPrincipal(const nsACString& aKey, ServiceWorkerManager::RegistrationDataPerPrincipal* aData, void* aUserData) { - UnregisterIfMatchesHostData data(aData, aUserData); + UnregisterIfMatchesHostOrPrincipalData data(aData, aUserData); aData->mInfos.EnumerateRead(UnregisterIfMatchesHost, &data); return PL_DHASH_NEXT; } PLDHashOperator +UnregisterIfMatchesPrincipal(const nsACString& aScope, + ServiceWorkerRegistrationInfo* aReg, + void* aPtr) +{ + UnregisterIfMatchesHostOrPrincipalData* data = + static_cast<UnregisterIfMatchesHostOrPrincipalData*>(aPtr); + + if (data->mUserData) { + nsIPrincipal *principal = static_cast<nsIPrincipal*>(data->mUserData); + MOZ_ASSERT(principal); + MOZ_ASSERT(aReg->mPrincipal); + bool equals; + aReg->mPrincipal->Equals(principal, &equals); + if (equals) { + nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); + swm->ForceUnregister(data->mRegistrationData, aReg); + } + } + + return PL_DHASH_NEXT; +} + +PLDHashOperator +UnregisterIfMatchesPrincipal(const nsACString& aKey, + ServiceWorkerManager::RegistrationDataPerPrincipal* aData, + void* aUserData) +{ + UnregisterIfMatchesHostOrPrincipalData data(aData, aUserData); + // We can use EnumerateRead because ForceUnregister (and Unregister) are async. + // Otherwise doing some R/W operations on an hashtable during an EnumerateRead + // will crash. + aData->mInfos.EnumerateRead(UnregisterIfMatchesPrincipal, &data); + return PL_DHASH_NEXT; +} + +PLDHashOperator GetAllRegistrationsEnumerator(const nsACString& aScope, ServiceWorkerRegistrationInfo* aReg, void* aData) { nsIMutableArray* array = static_cast<nsIMutableArray*>(aData); MOZ_ASSERT(aReg); if (aReg->mPendingUninstall) { @@ -4252,16 +4293,27 @@ UpdateEachRegistration(const nsACString& void* aUserArg) { auto This = static_cast<ServiceWorkerManager*>(aUserArg); MOZ_ASSERT(!aInfo->mScope.IsEmpty()); This->SoftUpdate(aInfo->mPrincipal, aInfo->mScope); return PL_DHASH_NEXT; } +void +ServiceWorkerManager::RemoveAllRegistrations(nsIPrincipal* aPrincipal) +{ + AssertIsOnMainThread(); + + MOZ_ASSERT(aPrincipal); + + mRegistrationInfos.EnumerateRead(UnregisterIfMatchesPrincipal, + aPrincipal); +} + static PLDHashOperator UpdateEachRegistrationPerPrincipal(const nsACString& aKey, ServiceWorkerManager::RegistrationDataPerPrincipal* aData, void* aUserArg) { aData->mInfos.EnumerateRead(UpdateEachRegistration, aUserArg); return PL_DHASH_NEXT; } @@ -4293,22 +4345,53 @@ ServiceWorkerManager::Observe(nsISupport RemoveAll(); } else if (strcmp(aTopic, PURGE_DOMAIN_DATA) == 0) { nsAutoString domain(aData); for (uint32_t i = 0; i < children.Length(); i++) { unused << children[i]->SendRemoveServiceWorkerRegistrationsForDomain(domain); } Remove(NS_ConvertUTF16toUTF8(domain)); + } else if (strcmp(aTopic, WEBAPPS_CLEAR_DATA) == 0) { + nsCOMPtr<mozIApplicationClearPrivateDataParams> params = + do_QueryInterface(aSubject); + if (NS_WARN_IF(!params)) { + return NS_OK; + } + + uint32_t appId; + nsresult rv = params->GetAppId(&appId); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIAppsService> appsService = + do_GetService(APPS_SERVICE_CONTRACTID); + if (NS_WARN_IF(!appsService)) { + return NS_OK; + } + + nsCOMPtr<mozIApplication> app; + appsService->GetAppByLocalId(appId, getter_AddRefs(app)); + if (NS_WARN_IF(!app)) { + return NS_OK; + } + + nsCOMPtr<nsIPrincipal> principal; + app->GetPrincipal(getter_AddRefs(principal)); + if (NS_WARN_IF(!principal)) { + return NS_OK; + } + + RemoveAllRegistrations(principal); } else if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); obs->RemoveObserver(this, PURGE_SESSION_HISTORY); obs->RemoveObserver(this, PURGE_DOMAIN_DATA); + obs->RemoveObserver(this, WEBAPPS_CLEAR_DATA); } } else { MOZ_CRASH("Received message we aren't supposed to be registered for!"); } return NS_OK; }
--- a/dom/workers/ServiceWorkerManager.h +++ b/dom/workers/ServiceWorkerManager.h @@ -527,16 +527,20 @@ private: // Does all cleanup except removing the registration from // mServiceWorkerRegistrationInfos. This is useful when we clear // registrations via remove()/removeAll() since we are iterating over the // hashtable and can cleanly remove within the hashtable enumeration // function. void RemoveRegistrationInternal(ServiceWorkerRegistrationInfo* aRegistration); + // Removes all service worker registrations for a given principal. + void + RemoveAllRegistrations(nsIPrincipal* aPrincipal); + nsRefPtr<ServiceWorkerManagerChild> mActor; struct PendingOperation; nsTArray<PendingOperation> mPendingOperations; }; } // namespace workers } // namespace dom