mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1191653 - Listen to clear-origin-data in nsPermissionManager. r=bholley
This commit is contained in:
parent
7144a02e76
commit
fb57af4ae6
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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<mozIApplicationClearPrivateDataParams> 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<nsIPermissionManager> 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<nsIObserverService> 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<nsIPermission> 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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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<length; ++i) {
|
||||
do_check_eq(pm.testPermissionFromPrincipal(principals[i], 'test/webapps-clear'), aResults[i]);
|
||||
do_check_eq(pm.testPermissionFromPrincipal(principals[i], 'test/clear-origin'), aResults[i]);
|
||||
|
||||
// Remove allowed actions.
|
||||
if (aResults[i] == pm.ALLOW_ACTION) {
|
||||
pm.removeFromPrincipal(principals[i], 'test/webapps-clear');
|
||||
pm.removeFromPrincipal(principals[i], 'test/clear-origin');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,16 +53,16 @@ function run_test()
|
||||
.getService(Ci.nsIPermissionManager);
|
||||
|
||||
let entries = [
|
||||
{ origin: 'http://example.com', appId: 1, browserElement: false },
|
||||
{ origin: 'http://example.com', appId: 1, browserElement: true },
|
||||
{ origin: 'http://example.com', appId: Ci.nsIScriptSecurityManager.NO_APPID, browserElement: false },
|
||||
{ origin: 'http://example.com', appId: 2, browserElement: false },
|
||||
{ origin: 'http://example.com', originAttributes: { appId: 1 } },
|
||||
{ origin: 'http://example.com', originAttributes: { appId: 1, inBrowser: true } },
|
||||
{ origin: 'http://example.com', originAttributes: {} },
|
||||
{ origin: 'http://example.com', originAttributes: { appId: 2 } },
|
||||
];
|
||||
|
||||
// In that case, all permissions from app 1 should be removed but not the other ones.
|
||||
test(entries, getSubject(1, false), [ pm.UNKNOWN_ACTION, pm.UNKNOWN_ACTION, pm.ALLOW_ACTION, pm.ALLOW_ACTION ]);
|
||||
test(entries, getData({appId: 1}), [ pm.UNKNOWN_ACTION, pm.UNKNOWN_ACTION, pm.ALLOW_ACTION, pm.ALLOW_ACTION ]);
|
||||
|
||||
// In that case, only the permissions of app 1 related to a browserElement should be removed.
|
||||
// All the other permissions should stay.
|
||||
test(entries, getSubject(1, true), [ pm.ALLOW_ACTION, pm.UNKNOWN_ACTION, pm.ALLOW_ACTION, pm.ALLOW_ACTION ]);
|
||||
test(entries, getData({appId: 1, inBrowser: true}), [ pm.ALLOW_ACTION, pm.UNKNOWN_ACTION, pm.ALLOW_ACTION, pm.ALLOW_ACTION ]);
|
||||
}
|
||||
|
@ -59,7 +59,8 @@ function run_test() {
|
||||
['http://mozilla.com', 1011, false, 'a', 1],
|
||||
];
|
||||
|
||||
pm.removePermissionsForApp(1001, false);
|
||||
let attrs = { appId: 1001 };
|
||||
pm.removePermissionsWithAttributes(JSON.stringify(attrs));
|
||||
checkPerms(remove_false_perms);
|
||||
|
||||
let restore = [
|
||||
@ -91,6 +92,8 @@ function run_test() {
|
||||
['http://mozilla.com', 1011, false, 'a', 1],
|
||||
];
|
||||
|
||||
pm.removePermissionsForApp(1001, true);
|
||||
attrs = { appId: 1001,
|
||||
inBrowser: true };
|
||||
pm.removePermissionsWithAttributes(JSON.stringify(attrs));
|
||||
checkPerms(remove_true_perms);
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ nsLayoutStatics::Initialize()
|
||||
|
||||
ProcessPriorityManager::Init();
|
||||
|
||||
nsPermissionManager::AppClearDataObserverInit();
|
||||
nsPermissionManager::ClearOriginDataObserverInit();
|
||||
nsCookieService::AppClearDataObserverInit();
|
||||
nsApplicationCacheService::AppClearDataObserverInit();
|
||||
|
||||
|
@ -37,7 +37,7 @@ interface nsIDOMWindow;
|
||||
interface nsIPermission;
|
||||
interface nsISimpleEnumerator;
|
||||
|
||||
[scriptable, uuid(0d1b8c65-0359-4a8c-b94d-4d3643b23e61)]
|
||||
[scriptable, uuid(a15cd7ef-f7a0-43d2-be86-8bf488dc760b)]
|
||||
interface nsIPermissionManager : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -234,13 +234,9 @@ interface nsIPermissionManager : nsISupports
|
||||
readonly attribute nsISimpleEnumerator enumerator;
|
||||
|
||||
/**
|
||||
* Remove all permissions associated with a given app id.
|
||||
* @param aAppId The appId of the app
|
||||
* @param aBrowserOnly Whether we should remove permissions associated with
|
||||
* a browser element (true) or all permissions (false).
|
||||
* Remove all permissions that will match the origin pattern.
|
||||
*/
|
||||
void removePermissionsForApp(in unsigned long appId,
|
||||
in boolean browserOnly);
|
||||
void removePermissionsWithAttributes(in DOMString patternAsJSON);
|
||||
|
||||
/**
|
||||
* If the current permission is set to expire, reset the expiration time. If
|
||||
|
Loading…
Reference in New Issue
Block a user