mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 786296 - Remove permissions when an app is uninstalled. r=jlebar,fabrice
This commit is contained in:
parent
5dac27b993
commit
41418e78b5
@ -47,6 +47,11 @@ AppsService.prototype = {
|
||||
return DOMApplicationRegistry.getManifestURLByLocalId(aLocalId);
|
||||
},
|
||||
|
||||
getAppFromObserverMessage: function getAppFromObserverMessage(aMessage) {
|
||||
debug("getAppFromObserverMessage( " + aMessage + " )");
|
||||
return DOMApplicationRegistry.getAppFromObserverMessage(aMessage);
|
||||
},
|
||||
|
||||
classID : APPS_SERVICE_CID,
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService])
|
||||
}
|
||||
|
@ -76,6 +76,11 @@ let DOMApplicationRegistry = {
|
||||
getManifestURLByLocalId: function getManifestURLByLocalId(aLocalId) {
|
||||
debug("getManifestURLByLocalId " + aLocalId);
|
||||
return AppsUtils.getManifestURLByLocalId(this.webapps, aLocalId);
|
||||
},
|
||||
|
||||
getAppFromObserverMessage: function getAppFromObserverMessage(aMessage) {
|
||||
debug("getAppFromObserverMessage " + aMessage);
|
||||
return AppsUtils.getAppFromObserverMessage(this.webapps. aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,5 +105,20 @@ let AppsUtils = {
|
||||
}
|
||||
|
||||
return "";
|
||||
},
|
||||
|
||||
getAppFromObserverMessage: function(aApps, aMessage) {
|
||||
let data = JSON.parse(aMessage);
|
||||
|
||||
for (let id in aApps) {
|
||||
let app = aApps[id];
|
||||
if (app.origin != data.origin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return this.cloneAsMozIApplication(app);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -780,6 +780,10 @@ let DOMApplicationRegistry = {
|
||||
return AppsUtils.getAppLocalIdByManifestURL(this.webapps, aManifestURL);
|
||||
},
|
||||
|
||||
getAppFromObserverMessage: function(aMessage) {
|
||||
return AppsUtils.getAppFromObserverMessage(this.webapps, aMessage);
|
||||
},
|
||||
|
||||
getAllWithoutManifests: function(aCallback) {
|
||||
let result = {};
|
||||
for (let id in this.webapps) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
* We expose Gecko-internal helpers related to "web apps" through this
|
||||
* sub-interface.
|
||||
*/
|
||||
[scriptable, uuid(acf46a46-729a-4ab4-9da3-8d59ecfd103d)]
|
||||
[scriptable, uuid(764e8930-ff06-4f23-9a6a-8523b93ac09f)]
|
||||
interface mozIApplication: mozIDOMApplication
|
||||
{
|
||||
/* Return true if this app has |permission|. */
|
||||
@ -19,4 +19,7 @@ interface mozIApplication: mozIDOMApplication
|
||||
|
||||
/* Application status as defined in nsIPrincipal. */
|
||||
readonly attribute unsigned short appStatus;
|
||||
|
||||
/* Returns the local id of the app (not the uuid used for sync). */
|
||||
readonly attribute unsigned long localId;
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "domstubs.idl"
|
||||
|
||||
interface mozIDOMApplication;
|
||||
interface mozIApplication;
|
||||
|
||||
%{C++
|
||||
#define APPS_SERVICE_CID { 0x05072afa, 0x92fe, 0x45bf, { 0xae, 0x22, 0x39, 0xb6, 0x9c, 0x11, 0x70, 0x58 } }
|
||||
@ -15,7 +16,7 @@ interface mozIDOMApplication;
|
||||
* This service allows accessing some DOMApplicationRegistry methods from
|
||||
* non-javascript code.
|
||||
*/
|
||||
[scriptable, uuid(04e4ef3c-1a30-45bc-ab08-291820f13872)]
|
||||
[scriptable, uuid(1f0ec00c-57c7-4ad2-a648-1359aa390360)]
|
||||
interface nsIAppsService : nsISupports
|
||||
{
|
||||
mozIDOMApplication getAppByManifestURL(in DOMString manifestURL);
|
||||
@ -37,4 +38,11 @@ interface nsIAppsService : nsISupports
|
||||
* Returns the manifest URL associated to this localId.
|
||||
*/
|
||||
DOMString getManifestURLByLocalId(in unsigned long localId);
|
||||
|
||||
/**
|
||||
* Returns the app that is related to the message.
|
||||
* This is a helper to not have to worry about what is the actual structure
|
||||
* of the message when listening to one.
|
||||
*/
|
||||
mozIApplication getAppFromObserverMessage(in DOMString message);
|
||||
};
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
<script>
|
||||
|
||||
steps = [get_installed_returns_nothing, install_super_crazy, get_self_returns_nothing,
|
||||
steps = [get_installed_returns_nothing, get_self_returns_nothing,
|
||||
install_wild_crazy, uninstall_wild_crazy, tearDown];
|
||||
|
||||
runAll(steps);
|
||||
@ -38,14 +38,6 @@ function get_installed_returns_nothing(next) {
|
||||
next);
|
||||
}
|
||||
|
||||
function install_super_crazy(next) {
|
||||
debug("in " + arguments.callee.name);
|
||||
var appURL = SERVERS['super_crazy'];
|
||||
install(appURL, ok, function() {
|
||||
getInstalled([appURL], ok, next);
|
||||
});
|
||||
}
|
||||
|
||||
function get_self_returns_nothing(next) {
|
||||
debug("in " + arguments.callee.name);
|
||||
mozAppscb(navigator.mozApps.getSelf(),
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "mozIApplication.h"
|
||||
|
||||
static nsPermissionManager *gPermissionManager = nullptr;
|
||||
|
||||
@ -121,6 +123,33 @@ GetHostForPrincipal(nsIPrincipal* aPrincipal, nsACString& aHost)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class AppUninstallObserver : public nsIObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIObserver implementation.
|
||||
NS_IMETHODIMP
|
||||
Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *data)
|
||||
{
|
||||
MOZ_ASSERT(!nsCRT::strcmp(aTopic, "webapps-uninstall"));
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService("@mozilla.org/AppsService;1");
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
|
||||
appsService->GetAppFromObserverMessage(nsAutoString(data), getter_AddRefs(app));
|
||||
NS_ENSURE_TRUE(app, NS_ERROR_UNEXPECTED);
|
||||
|
||||
uint32_t appId;
|
||||
app->GetLocalId(&appId);
|
||||
MOZ_ASSERT(appId != nsIScriptSecurityManager::NO_APP_ID);
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permManager = do_GetService("@mozilla.org/permissionmanager;1");
|
||||
return permManager->RemovePermissionsForApp(appId);
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(AppUninstallObserver, nsIObserver)
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -238,6 +267,13 @@ NS_IMETHODIMP DeleteFromMozHostListener::HandleCompletion(uint16_t aReason)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsPermissionManager::AppUninstallObserverInit()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
|
||||
observerService->AddObserver(new AppUninstallObserver(), "webapps-uninstall", /* holdsWeak= */ false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsPermissionManager Implementation
|
||||
|
||||
@ -1071,6 +1107,85 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsPermissionManager::GetPermissionsForApp(nsPermissionManager::PermissionHashKey* entry, void* arg)
|
||||
{
|
||||
GetPermissionsForAppStruct* data = static_cast<GetPermissionsForAppStruct*>(arg);
|
||||
|
||||
for (uint32_t i = 0; i < entry->GetPermissions().Length(); ++i) {
|
||||
nsPermissionManager::PermissionEntry& permEntry = entry->GetPermissions()[i];
|
||||
|
||||
if (entry->GetKey()->mAppId != data->appId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data->permissions.AppendObject(new nsPermission(entry->GetKey()->mHost,
|
||||
entry->GetKey()->mAppId,
|
||||
entry->GetKey()->mIsInBrowserElement,
|
||||
gPermissionManager->mTypeArray.ElementAt(permEntry.mType),
|
||||
permEntry.mPermission,
|
||||
permEntry.mExpireType,
|
||||
permEntry.mExpireTime));
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId)
|
||||
{
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
NS_ENSURE_ARG(aAppId != nsIScriptSecurityManager::NO_APP_ID);
|
||||
|
||||
// We begin by removing all the permissions from the DB.
|
||||
// This is not using a mozIStorageStatement because removing an app should be
|
||||
// rare enough to not have to worry too much about performance.
|
||||
// After clearing the DB, we call AddInternal() to make sure that all
|
||||
// processes are aware of this change and the representation of the DB in
|
||||
// memory is updated.
|
||||
// We have to get all permissions associated with an application and then
|
||||
// remove those because doing so in EnumerateEntries() would fail because
|
||||
// we might happen to actually delete entries from the list.
|
||||
|
||||
nsCAutoString sql;
|
||||
sql.AppendLiteral("DELETE FROM moz_hosts WHERE appId=");
|
||||
sql.AppendInt(aAppId);
|
||||
|
||||
nsresult rv = mDBConn->ExecuteSimpleSQL(sql);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
GetPermissionsForAppStruct data(aAppId);
|
||||
mPermissionTable.EnumerateEntries(GetPermissionsForApp, &data);
|
||||
|
||||
for (int32_t i=0; i<data.permissions.Count(); ++i) {
|
||||
nsCAutoString host;
|
||||
bool isInBrowserElement;
|
||||
nsCAutoString type;
|
||||
|
||||
data.permissions[i]->GetHost(host);
|
||||
data.permissions[i]->GetIsInBrowserElement(&isInBrowserElement);
|
||||
data.permissions[i]->GetType(type);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
if (NS_FAILED(GetPrincipal(host, aAppId, isInBrowserElement,
|
||||
getter_AddRefs(principal)))) {
|
||||
NS_ERROR("GetPrincipal() failed!");
|
||||
continue;
|
||||
}
|
||||
|
||||
AddInternal(principal,
|
||||
type,
|
||||
nsIPermissionManager::UNKNOWN_ACTION,
|
||||
0,
|
||||
nsIPermissionManager::EXPIRE_NEVER,
|
||||
0,
|
||||
nsPermissionManager::eNotify,
|
||||
nsPermissionManager::eNoDBOperation);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*** nsPermissionManager private methods
|
||||
//*****************************************************************************
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "nsPermission.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsIPermission;
|
||||
class nsIIDNService;
|
||||
@ -190,6 +191,14 @@ public:
|
||||
NotifyOperationType aNotifyOperation,
|
||||
DBOperationType aDBOperation);
|
||||
|
||||
/**
|
||||
* Initialize the "webapp-uninstall" 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 AppUninstallObserverInit();
|
||||
|
||||
private:
|
||||
int32_t GetTypeIndex(const char *aTypeString,
|
||||
bool aAdd);
|
||||
@ -237,6 +246,28 @@ private:
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement);
|
||||
|
||||
/**
|
||||
* This struct has to be passed as an argument to GetPermissionsForApp.
|
||||
* |appId| has to be defined.
|
||||
* |permissions| will be filed with permissions that are related to the app.
|
||||
*/
|
||||
struct GetPermissionsForAppStruct {
|
||||
uint32_t appId;
|
||||
nsCOMArray<nsIPermission> permissions;
|
||||
|
||||
GetPermissionsForAppStruct() MOZ_DELETE;
|
||||
GetPermissionsForAppStruct(uint32_t aAppId)
|
||||
: appId(aAppId)
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* This method will return the list of all permissions that are related to a
|
||||
* specific app.
|
||||
* @param arg has to be an instance of GetPermissionsForAppStruct.
|
||||
*/
|
||||
static PLDHashOperator GetPermissionsForApp(nsPermissionManager::PermissionHashKey* entry, void* arg);
|
||||
|
||||
nsCOMPtr<nsIObserverService> mObserverService;
|
||||
nsCOMPtr<nsIIDNService> mIDNService;
|
||||
|
||||
|
@ -54,6 +54,7 @@ MOCHITEST_FILES = \
|
||||
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
test_permissionmanager_app_isolation.html \
|
||||
test_app_uninstall.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_BROWSER_FILES = \
|
||||
|
129
extensions/cookie/test/test_app_uninstall.html
Normal file
129
extensions/cookie/test/test_app_uninstall.html
Normal file
@ -0,0 +1,129 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=786296
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests that uninstalling app removes the permissions</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786296">Mozilla Bug 786296</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 786296 **/
|
||||
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var permManager = Cc["@mozilla.org/permissionmanager;1"]
|
||||
.getService(Ci.nsIPermissionManager);
|
||||
var appsService = Cc['@mozilla.org/AppsService;1']
|
||||
.getService(Ci.nsIAppsService);
|
||||
var secMan = Cc['@mozilla.org/scriptsecuritymanager;1']
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
var ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
|
||||
function confirmNextInstall() {
|
||||
var panel = window.top.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler.ownerDocument.defaultView
|
||||
.PopupNotifications.panel
|
||||
|
||||
panel.addEventListener("popupshown", function() {
|
||||
panel.removeEventListener("popupshown", arguments.callee, false);
|
||||
this.childNodes[0].button.doCommand();
|
||||
}, false);
|
||||
}
|
||||
|
||||
// If aAppId = -1, returns permissions count, regardless of app.
|
||||
function getPermissionCountForApp(aAppId) {
|
||||
var nbPermissions = 0;
|
||||
var enumerator = permManager.enumerator;
|
||||
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
|
||||
|
||||
if (permission.appId == aAppId || aAppId == -1) {
|
||||
nbPermissions++;
|
||||
}
|
||||
}
|
||||
|
||||
return nbPermissions;
|
||||
}
|
||||
|
||||
var previousDryRunValue = null;
|
||||
try {
|
||||
previousDryRunValue = SpecialPowers.getBoolPref('browser.mozApps.installer.dry_run');
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
SpecialPowers.setBoolPref('browser.mozApps.installer.dry_run', true);
|
||||
permManager.addFromPrincipal(window.document.nodePrincipal, "webapps-manage",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
|
||||
var gManifestURL = "http://www.example.com:80/chrome/dom/tests/mochitest/webapps/apps/super_crazy.webapp";
|
||||
|
||||
confirmNextInstall();
|
||||
|
||||
navigator.mozApps.install(gManifestURL, null).onsuccess = function() {
|
||||
var testAppId = appsService.getAppLocalIdByManifestURL(gManifestURL);
|
||||
|
||||
is(getPermissionCountForApp(testAppId), 0, "App should have no permission");
|
||||
|
||||
var currentPermissionCount = getPermissionCountForApp(-1);
|
||||
|
||||
var principal = secMan.getAppCodebasePrincipal(ioService.newURI("http://www.example.com", null, null),
|
||||
testAppId, false);
|
||||
|
||||
permManager.addFromPrincipal(principal, "foobar", Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
permManager.addFromPrincipal(principal, "foo", Ci.nsIPermissionManager.DENY_ACTION);
|
||||
permManager.addFromPrincipal(principal, "bar", Ci.nsIPermissionManager.ALLOW_ACTION, Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
||||
|
||||
principal = secMan.getAppCodebasePrincipal(ioService.newURI("http://www.example.com", null, null),
|
||||
testAppId, true);
|
||||
permManager.addFromPrincipal(principal, "foobar", Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
|
||||
principal = secMan.getAppCodebasePrincipal(ioService.newURI("http://www.example.org", null, null),
|
||||
testAppId, false);
|
||||
permManager.addFromPrincipal(principal, "foobar", Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
|
||||
is(getPermissionCountForApp(testAppId), 5, "App should have 5 permissions");
|
||||
|
||||
// Not installed means not installed as native app.
|
||||
navigator.mozApps.mgmt.getNotInstalled().onsuccess = function() {
|
||||
for (i in this.result) {
|
||||
var app = this.result[i];
|
||||
if (app.manifestURL == gManifestURL) {
|
||||
app.uninstall().onsuccess = function() {
|
||||
is(getPermissionCountForApp(testAppId), 0, "App should have no permissions");
|
||||
|
||||
is(getPermissionCountForApp(-1), currentPermissionCount,
|
||||
"Number of permissions should not have changed");
|
||||
|
||||
SpecialPowers.setBoolPref('browser.mozApps.installer.dry_run', previousDryRunValue);
|
||||
permManager.removeFromPrincipal(window.document.nodePrincipal, "webapps-manage",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -266,6 +266,7 @@ LOCAL_INCLUDES += -I$(srcdir)/../base \
|
||||
-I$(topsrcdir)/caps/include \
|
||||
-I$(topsrcdir)/netwerk/base/src \
|
||||
-I$(topsrcdir)/content/svg/content/src \
|
||||
-I$(topsrcdir)/extensions/cookie \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G_RIL #{
|
||||
|
@ -98,6 +98,7 @@
|
||||
#include "nsWindowMemoryReporter.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ipc/ProcessPriorityManager.h"
|
||||
#include "nsPermissionManager.h"
|
||||
|
||||
extern void NS_ShutdownChainItemPool();
|
||||
|
||||
@ -252,6 +253,8 @@ nsLayoutStatics::Initialize()
|
||||
|
||||
InitProcessPriorityManager();
|
||||
|
||||
nsPermissionManager::AppUninstallObserverInit();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ interface nsIURI;
|
||||
interface nsIObserver;
|
||||
interface nsIPrincipal;
|
||||
|
||||
[scriptable, uuid(cc423aaf-f088-4ec2-86ef-7733225773f9)]
|
||||
[scriptable, uuid(da33450a-f3cb-4fdb-93ee-219644e450c2)]
|
||||
interface nsIPermissionManager : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -169,6 +169,11 @@ interface nsIPermissionManager : nsISupports
|
||||
* nsIPermission objects
|
||||
*/
|
||||
readonly attribute nsISimpleEnumerator enumerator;
|
||||
|
||||
/**
|
||||
* Remove all permissions associated with a given app id.
|
||||
*/
|
||||
void removePermissionsForApp(in unsigned long appId);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
|
Loading…
Reference in New Issue
Block a user