From fb57af4ae67a02f1ea05b9d9573a4d6fb10c6ff0 Mon Sep 17 00:00:00 2001 From: Yoshi Huang Date: Tue, 13 Oct 2015 10:27:42 +0800 Subject: [PATCH] Bug 1191653 - Listen to clear-origin-data in nsPermissionManager. r=bholley --- caps/tests/unit/test_origin.js | 4 +- dom/apps/Webapps.jsm | 3 +- extensions/cookie/nsPermissionManager.cpp | 53 ++++++++----------- extensions/cookie/nsPermissionManager.h | 11 +++- .../test/unit/test_permmanager_cleardata.js | 47 ++++++++-------- .../unit/test_permmanager_removeforapp.js | 7 ++- layout/build/nsLayoutStatics.cpp | 2 +- netwerk/base/nsIPermissionManager.idl | 10 ++-- 8 files changed, 65 insertions(+), 72 deletions(-) diff --git a/caps/tests/unit/test_origin.js b/caps/tests/unit/test_origin.js index 511837f8c674..30b9e367d252 100644 --- a/caps/tests/unit/test_origin.js +++ b/caps/tests/unit/test_origin.js @@ -26,6 +26,8 @@ function checkOriginAttributes(prin, attrs, suffix) { do_check_eq(prin.originAttributes.appId, attrs.appId || 0); do_check_eq(prin.originAttributes.inBrowser, attrs.inBrowser || false); do_check_eq(prin.originSuffix, suffix || ''); + do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), suffix || ''); + do_check_true(ChromeUtils.originAttributesMatchPattern(prin.originAttributes, attrs)); if (!prin.isNullPrincipal && !prin.origin.startsWith('[')) { do_check_true(ssm.createCodebasePrincipalFromOrigin(prin.origin).equals(prin)); } else { @@ -133,7 +135,7 @@ function run_test() { // Just signedPkg var exampleOrg_signedPkg = ssm.createCodebasePrincipal(makeURI('http://example.org'), {signedPkg: 'whatever'}); - checkOriginAttributes(exampleOrg_signedPkg, { signedPkg: 'id' }, '^signedPkg=whatever'); + checkOriginAttributes(exampleOrg_signedPkg, { signedPkg: 'whatever' }, '^signedPkg=whatever'); do_check_eq(exampleOrg_signedPkg.origin, 'http://example.org^signedPkg=whatever'); // signedPkg and browser diff --git a/dom/apps/Webapps.jsm b/dom/apps/Webapps.jsm index ef449e49884d..f2613c2a1217 100644 --- a/dom/apps/Webapps.jsm +++ b/dom/apps/Webapps.jsm @@ -696,7 +696,8 @@ this.DOMApplicationRegistry = { continue; // Remove the permissions, cookies and private data for this app. let localId = this.webapps[id].localId; - permMgr.removePermissionsForApp(localId, false); + let attrs = { appId: localId }; + permMgr.removePermissionsWithAttributes(JSON.stringify(attrs)); Services.cookies.removeCookiesForApp(localId, false); this._clearPrivateData(localId, false); delete this.webapps[id]; diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp index 1f50cfdc099a..d8a4f290a6ba 100644 --- a/extensions/cookie/nsPermissionManager.cpp +++ b/extensions/cookie/nsPermissionManager.cpp @@ -31,7 +31,6 @@ #include "nsIScriptSecurityManager.h" #include "nsIAppsService.h" #include "mozIApplication.h" -#include "mozIApplicationClearPrivateDataParams.h" #include "nsIEffectiveTLDService.h" #include "nsPIDOMWindow.h" #include "nsIDocument.h" @@ -167,39 +166,24 @@ GetNextSubDomainForHost(const nsACString& aHost) return subDomain; } -class AppClearDataObserver final : public nsIObserver { - ~AppClearDataObserver() {} +class ClearOriginDataObserver final : public nsIObserver { + ~ClearOriginDataObserver() {} public: NS_DECL_ISUPPORTS // nsIObserver implementation. NS_IMETHODIMP - Observe(nsISupports *aSubject, const char *aTopic, const char16_t *data) override + Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) override { - MOZ_ASSERT(!nsCRT::strcmp(aTopic, "webapps-clear-data")); - - nsCOMPtr params = - do_QueryInterface(aSubject); - if (!params) { - NS_ERROR("'webapps-clear-data' notification's subject should be a mozIApplicationClearPrivateDataParams"); - return NS_ERROR_UNEXPECTED; - } - - uint32_t appId; - nsresult rv = params->GetAppId(&appId); - NS_ENSURE_SUCCESS(rv, rv); - - bool browserOnly; - rv = params->GetBrowserOnly(&browserOnly); - NS_ENSURE_SUCCESS(rv, rv); + MOZ_ASSERT(!nsCRT::strcmp(aTopic, "clear-origin-data")); nsCOMPtr permManager = do_GetService("@mozilla.org/permissionmanager;1"); - return permManager->RemovePermissionsForApp(appId, browserOnly); + return permManager->RemovePermissionsWithAttributes(nsDependentString(aData)); } }; -NS_IMPL_ISUPPORTS(AppClearDataObserver, nsIObserver) +NS_IMPL_ISUPPORTS(ClearOriginDataObserver, nsIObserver) class MOZ_STACK_CLASS UpgradeHostToOriginHelper { public: @@ -709,11 +693,11 @@ NS_IMETHODIMP DeleteFromMozHostListener::HandleCompletion(uint16_t aReason) } /* static */ void -nsPermissionManager::AppClearDataObserverInit() +nsPermissionManager::ClearOriginDataObserverInit() { nsCOMPtr observerService = mozilla::services::GetObserverService(); - observerService->AddObserver(new AppClearDataObserver(), "webapps-clear-data", /* holdsWeak= */ false); + observerService->AddObserver(new ClearOriginDataObserver(), "clear-origin-data", /* holdsWeak= */ false); } //////////////////////////////////////////////////////////////////////////////// @@ -2308,11 +2292,20 @@ nsPermissionManager::RemoveAllModifiedSince(int64_t aModificationTime) } NS_IMETHODIMP -nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId, bool aBrowserOnly) +nsPermissionManager::RemovePermissionsWithAttributes(const nsAString& aPattern) { ENSURE_NOT_CHILD_PROCESS; - NS_ENSURE_ARG(aAppId != nsIScriptSecurityManager::NO_APP_ID); + mozilla::OriginAttributesPattern pattern; + if (!pattern.Init(aPattern)) { + return NS_ERROR_INVALID_ARG; + } + return RemovePermissionsWithAttributes(pattern); +} + +nsresult +nsPermissionManager::RemovePermissionsWithAttributes(mozilla::OriginAttributesPattern& aPattern) +{ nsCOMArray permissions; for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) { PermissionHashKey* entry = iter.Get(); @@ -2324,12 +2317,7 @@ nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId, bool aBrowserOnly) continue; } - uint32_t appId; - bool isInBrowserElement; - principal->GetAppId(&appId); - principal->GetIsInBrowserElement(&isInBrowserElement); - - if (appId != aAppId || (aBrowserOnly && !isInBrowserElement)) { + if (!aPattern.Matches(mozilla::BasePrincipal::Cast(principal)->OriginAttributesRef())) { continue; } @@ -2955,3 +2943,4 @@ nsPermissionManager::FetchPermissions() { } return NS_OK; } + diff --git a/extensions/cookie/nsPermissionManager.h b/extensions/cookie/nsPermissionManager.h index 88ef9cb611a7..a75b2d62b6f4 100644 --- a/extensions/cookie/nsPermissionManager.h +++ b/extensions/cookie/nsPermissionManager.h @@ -20,6 +20,10 @@ #include "nsCOMArray.h" #include "nsDataHashtable.h" +namespace mozilla { +class OriginAttributesPattern; +} + class nsIPermission; class mozIStorageConnection; class mozIStorageAsyncStatement; @@ -194,12 +198,15 @@ public: const bool aIgnoreSessionPermissions = false); /** - * Initialize the "webapp-uninstall" observing. + * Initialize the "clear-origin-data" observing. * Will create a nsPermissionManager instance if needed. * That way, we can prevent have nsPermissionManager created at startup just * to be able to clear data when an application is uninstalled. */ - static void AppClearDataObserverInit(); + static void ClearOriginDataObserverInit(); + + nsresult + RemovePermissionsWithAttributes(mozilla::OriginAttributesPattern& aAttrs); private: virtual ~nsPermissionManager(); diff --git a/extensions/cookie/test/unit/test_permmanager_cleardata.js b/extensions/cookie/test/unit/test_permmanager_cleardata.js index cd613bc5e310..16c33bd75a59 100644 --- a/extensions/cookie/test/unit/test_permmanager_cleardata.js +++ b/extensions/cookie/test/unit/test_permmanager_cleardata.js @@ -3,49 +3,44 @@ var pm; -// Create a principal based on the { origin, appId, browserElement }. -function createPrincipal(aOrigin, aAppId, aBrowserElement) +// Create a principal based on the { origin, originAttributes }. +function createPrincipal(aOrigin, aOriginAttributes) { - var attrs = {appId: aAppId, inBrowser: aBrowserElement}; - return Services.scriptSecurityManager.createCodebasePrincipal(NetUtil.newURI(aOrigin), attrs); + return Services.scriptSecurityManager.createCodebasePrincipal(NetUtil.newURI(aOrigin), aOriginAttributes); } -// Return the subject required by 'webapps-clear-data' notification. -function getSubject(aAppId, aBrowserOnly) +// Return the data required by 'clear-origin-data' notification. +function getData(aPattern) { - return { - appId: aAppId, - browserOnly: aBrowserOnly, - QueryInterface: XPCOMUtils.generateQI([Ci.mozIApplicationClearPrivateDataParams]) - }; + return JSON.stringify(aPattern); } // Use aEntries to create principals, add permissions to them and check that they have them. -// Then, it is notifying 'webapps-clear-data' with the given aSubject and check if the permissions +// Then, it is notifying 'clear-origin-data' with the given aData and check if the permissions // of principals[i] matches the permission in aResults[i]. -function test(aEntries, aSubject, aResults) +function test(aEntries, aData, aResults) { let principals = []; for (entry of aEntries) { - principals.push(createPrincipal(entry.origin, entry.appId, entry.browserElement)); + principals.push(createPrincipal(entry.origin, entry.originAttributes)); } for (principal of principals) { - do_check_eq(pm.testPermissionFromPrincipal(principal, "test/webapps-clear"), pm.UNKNOWN_ACTION); - pm.addFromPrincipal(principal, "test/webapps-clear", pm.ALLOW_ACTION, pm.EXPIRE_NEVER, 0); - do_check_eq(pm.testPermissionFromPrincipal(principal, "test/webapps-clear"), pm.ALLOW_ACTION); + do_check_eq(pm.testPermissionFromPrincipal(principal, "test/clear-origin"), pm.UNKNOWN_ACTION); + pm.addFromPrincipal(principal, "test/clear-origin", pm.ALLOW_ACTION, pm.EXPIRE_NEVER, 0); + do_check_eq(pm.testPermissionFromPrincipal(principal, "test/clear-origin"), pm.ALLOW_ACTION); } - Services.obs.notifyObservers(aSubject, 'webapps-clear-data', null); + Services.obs.notifyObservers(null, 'clear-origin-data', aData); var length = aEntries.length; for (let i=0; i