mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 811026 - [Permissions] Grant a prompted permission for the duration of the session, r=sicking
This commit is contained in:
parent
a9fccc4e48
commit
1a0052f653
@ -35,7 +35,7 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"@mozilla.org/permissionSettings;1",
|
||||
"nsIDOMPermissionSettings");
|
||||
|
||||
function rememberPermission(aPermission, aPrincipal)
|
||||
function rememberPermission(aPermission, aPrincipal, aSession)
|
||||
{
|
||||
function convertPermToAllow(aPerm, aPrincipal)
|
||||
{
|
||||
@ -44,9 +44,16 @@ function rememberPermission(aPermission, aPrincipal)
|
||||
if (type == Ci.nsIPermissionManager.PROMPT_ACTION ||
|
||||
(type == Ci.nsIPermissionManager.UNKNOWN_ACTION &&
|
||||
PROMPT_FOR_UNKNOWN.indexOf(aPermission) >= 0)) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
if (!aSession) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
} else {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,10 +109,7 @@ ContentPermissionPrompt.prototype = {
|
||||
evt.target.removeEventListener(evt.type, contentEvent);
|
||||
|
||||
if (evt.detail.type == "permission-allow") {
|
||||
if (evt.detail.remember) {
|
||||
rememberPermission(request.type, request.principal);
|
||||
}
|
||||
|
||||
rememberPermission(request.type, request.principal, !evt.detail.remember);
|
||||
request.allow();
|
||||
return;
|
||||
}
|
||||
@ -113,6 +117,10 @@ ContentPermissionPrompt.prototype = {
|
||||
if (evt.detail.remember) {
|
||||
Services.perms.addFromPrincipal(request.principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
} else {
|
||||
Services.perms.addFromPrincipal(request.principal, access,
|
||||
Ci.nsIPermissionManager.DENY_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
||||
}
|
||||
|
||||
request.cancel();
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIEditorDocShell.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsView.h"
|
||||
@ -282,6 +283,7 @@ NS_INTERFACE_MAP_END
|
||||
|
||||
nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
|
||||
: mOwnerContent(aOwner)
|
||||
, mAppIdSentToPermissionManager(nsIScriptSecurityManager::NO_APP_ID)
|
||||
, mDetachedSubdocViews(nullptr)
|
||||
, mDepthTooGreat(false)
|
||||
, mIsTopLevelContent(false)
|
||||
@ -303,6 +305,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
|
||||
, mRenderMode(RENDER_MODE_DEFAULT)
|
||||
, mEventMode(EVENT_MODE_NORMAL_DISPATCH)
|
||||
{
|
||||
ResetPermissionManagerStatus();
|
||||
}
|
||||
|
||||
nsFrameLoader*
|
||||
@ -1404,6 +1407,8 @@ nsFrameLoader::SetOwnerContent(Element* aContent)
|
||||
if (RenderFrameParent* rfp = GetCurrentRemoteFrame()) {
|
||||
rfp->OwnerContentChanged(aContent);
|
||||
}
|
||||
|
||||
ResetPermissionManagerStatus();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2541,3 +2546,59 @@ nsFrameLoader::AttributeChanged(nsIDocument* aDocument,
|
||||
is_targetable, value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameLoader::ResetPermissionManagerStatus()
|
||||
{
|
||||
// Finding the new app Id:
|
||||
// . first we check if the owner is an app frame
|
||||
// . second, we check if the owner is a browser frame
|
||||
// in both cases we populate the appId variable.
|
||||
uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (OwnerIsAppFrame()) {
|
||||
// You can't be both an app and a browser frame.
|
||||
MOZ_ASSERT(!OwnerIsBrowserFrame());
|
||||
|
||||
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
||||
MOZ_ASSERT(ownApp);
|
||||
uint32_t ownAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (ownApp && NS_SUCCEEDED(ownApp->GetLocalId(&ownAppId))) {
|
||||
appId = ownAppId;
|
||||
}
|
||||
}
|
||||
|
||||
if (OwnerIsBrowserFrame()) {
|
||||
// You can't be both a browser and an app frame.
|
||||
MOZ_ASSERT(!OwnerIsAppFrame());
|
||||
|
||||
nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
|
||||
uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (containingApp && NS_SUCCEEDED(containingApp->GetLocalId(&containingAppId))) {
|
||||
appId = containingAppId;
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing changed.
|
||||
if (appId == mAppIdSentToPermissionManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permMgr = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
if (!permMgr) {
|
||||
NS_ERROR("No PermissionManager available!");
|
||||
return;
|
||||
}
|
||||
|
||||
// If previously we registered an appId, we have to unregister it.
|
||||
if (mAppIdSentToPermissionManager != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
permMgr->ReleaseAppId(mAppIdSentToPermissionManager);
|
||||
mAppIdSentToPermissionManager = nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
// Register the new AppId.
|
||||
if (appId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
mAppIdSentToPermissionManager = appId;
|
||||
permMgr->AddrefAppId(mAppIdSentToPermissionManager);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,10 +381,17 @@ private:
|
||||
return mOwnerContent->IsXUL() ? nsGkAtoms::type : nsGkAtoms::mozframetype;
|
||||
}
|
||||
|
||||
// Update the permission manager's app-id refcount based on mOwnerContent's
|
||||
// own-or-containing-app.
|
||||
void ResetPermissionManagerStatus();
|
||||
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
nsCOMPtr<nsIURI> mURIToLoad;
|
||||
mozilla::dom::Element* mOwnerContent; // WEAK
|
||||
|
||||
// Note: this variable must be modified only by ResetPermissionManagerStatus()
|
||||
uint32_t mAppIdSentToPermissionManager;
|
||||
|
||||
public:
|
||||
// public because a callback needs these.
|
||||
nsRefPtr<nsFrameMessageManager> mMessageManager;
|
||||
|
@ -660,9 +660,9 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
|
||||
// changed and the expire type is time, otherwise, don't modify. There's
|
||||
// no need to modify a permission that doesn't expire with time when the
|
||||
// only thing changed is the expire time.
|
||||
if (aPermission == oldPermissionEntry.mPermission &&
|
||||
if (aPermission == oldPermissionEntry.mPermission &&
|
||||
aExpireType == oldPermissionEntry.mExpireType &&
|
||||
(aExpireType != nsIPermissionManager::EXPIRE_TIME ||
|
||||
(aExpireType != nsIPermissionManager::EXPIRE_TIME ||
|
||||
aExpireTime == oldPermissionEntry.mExpireTime))
|
||||
op = eOperationNone;
|
||||
else if (aPermission == nsIPermissionManager::UNKNOWN_ACTION)
|
||||
@ -753,6 +753,15 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
|
||||
case eOperationChanging:
|
||||
{
|
||||
id = entry->GetPermissions()[index].mID;
|
||||
|
||||
// If the new expireType is EXPIRE_SESSION, then we have to keep a
|
||||
// copy of the previous permission value. This cached value will be
|
||||
// used when restoring the permissions of an app.
|
||||
if (entry->GetPermissions()[index].mExpireType != nsIPermissionManager::EXPIRE_SESSION &&
|
||||
aExpireType == nsIPermissionManager::EXPIRE_SESSION) {
|
||||
entry->GetPermissions()[index].mNonSessionPermission = entry->GetPermissions()[index].mPermission;
|
||||
}
|
||||
|
||||
entry->GetPermissions()[index].mPermission = aPermission;
|
||||
|
||||
if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION)
|
||||
@ -1204,6 +1213,64 @@ nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsPermissionManager::RemoveExpiredPermissionsForAppEnumerator(
|
||||
nsPermissionManager::PermissionHashKey* entry, void* arg)
|
||||
{
|
||||
uint32_t* appId = static_cast<uint32_t*>(arg);
|
||||
|
||||
for (uint32_t i = 0; i < entry->GetPermissions().Length(); ++i) {
|
||||
if (entry->GetKey()->mAppId != *appId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsPermissionManager::PermissionEntry& permEntry = entry->GetPermissions()[i];
|
||||
if (permEntry.mExpireType == nsIPermissionManager::EXPIRE_SESSION) {
|
||||
PermissionEntry oldPermissionEntry = entry->GetPermissions()[i];
|
||||
|
||||
entry->GetPermissions().RemoveElementAt(i);
|
||||
|
||||
gPermissionManager->NotifyObserversWithPermission(entry->GetKey()->mHost,
|
||||
entry->GetKey()->mAppId,
|
||||
entry->GetKey()->mIsInBrowserElement,
|
||||
gPermissionManager->mTypeArray.ElementAt(oldPermissionEntry.mType),
|
||||
oldPermissionEntry.mPermission,
|
||||
oldPermissionEntry.mExpireType,
|
||||
oldPermissionEntry.mExpireTime,
|
||||
NS_LITERAL_STRING("deleted").get());
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (permEntry.mNonSessionPermission != permEntry.mPermission) {
|
||||
permEntry.mPermission = permEntry.mNonSessionPermission;
|
||||
|
||||
gPermissionManager->NotifyObserversWithPermission(entry->GetKey()->mHost,
|
||||
entry->GetKey()->mAppId,
|
||||
entry->GetKey()->mIsInBrowserElement,
|
||||
gPermissionManager->mTypeArray.ElementAt(permEntry.mType),
|
||||
permEntry.mPermission,
|
||||
permEntry.mExpireType,
|
||||
permEntry.mExpireTime,
|
||||
NS_LITERAL_STRING("changed").get());
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPermissionManager::RemoveExpiredPermissionsForApp(uint32_t aAppId)
|
||||
{
|
||||
ENSURE_NOT_CHILD_PROCESS;
|
||||
|
||||
if (aAppId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
mPermissionTable.EnumerateEntries(RemoveExpiredPermissionsForAppEnumerator, &aAppId);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*** nsPermissionManager private methods
|
||||
//*****************************************************************************
|
||||
@ -1418,10 +1485,10 @@ nsPermissionManager::Import()
|
||||
|
||||
// Split the line at tabs
|
||||
ParseString(buffer, '\t', lineArray);
|
||||
|
||||
|
||||
if (lineArray[0].EqualsLiteral(kMatchTypeHost) &&
|
||||
lineArray.Length() == 4) {
|
||||
|
||||
|
||||
nsresult error;
|
||||
uint32_t permission = lineArray[2].ToInteger(&error);
|
||||
if (NS_FAILED(error))
|
||||
@ -1491,7 +1558,7 @@ nsPermissionManager::UpdateDB(OperationType aOp,
|
||||
|
||||
rv = aStmt->BindUTF8StringByIndex(1, aHost);
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
|
||||
rv = aStmt->BindUTF8StringByIndex(2, aType);
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
@ -1550,3 +1617,51 @@ nsPermissionManager::UpdateDB(OperationType aOp,
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::AddrefAppId(uint32_t aAppId)
|
||||
{
|
||||
if (aAppId == nsIScriptSecurityManager::NO_APP_ID) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (uint32_t i = 0; i < mAppIdRefcounts.Length(); ++i) {
|
||||
if (mAppIdRefcounts[i].mAppId == aAppId) {
|
||||
++mAppIdRefcounts[i].mCounter;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
ApplicationCounter app = { aAppId, 1 };
|
||||
mAppIdRefcounts.AppendElement(app);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPermissionManager::ReleaseAppId(uint32_t aAppId)
|
||||
{
|
||||
// An app has been released, maybe we have to reset its session.
|
||||
|
||||
if (aAppId == nsIScriptSecurityManager::NO_APP_ID) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mAppIdRefcounts.Length(); ++i) {
|
||||
if (mAppIdRefcounts[i].mAppId == aAppId) {
|
||||
--mAppIdRefcounts[i].mCounter;
|
||||
|
||||
if (!mAppIdRefcounts[i].mCounter) {
|
||||
mAppIdRefcounts.RemoveElementAt(i);
|
||||
return RemoveExpiredPermissionsForApp(aAppId);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
class nsIPermission;
|
||||
class nsIIDNService;
|
||||
@ -42,6 +43,7 @@ public:
|
||||
, mPermission(aPermission)
|
||||
, mExpireType(aExpireType)
|
||||
, mExpireTime(aExpireTime)
|
||||
, mNonSessionPermission(aPermission)
|
||||
{}
|
||||
|
||||
int64_t mID;
|
||||
@ -49,6 +51,7 @@ public:
|
||||
uint32_t mPermission;
|
||||
uint32_t mExpireType;
|
||||
int64_t mExpireTime;
|
||||
uint32_t mNonSessionPermission;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -246,6 +249,8 @@ private:
|
||||
uint32_t aAppId,
|
||||
bool aIsInBrowserElement);
|
||||
|
||||
nsresult RemoveExpiredPermissionsForApp(uint32_t aAppId);
|
||||
|
||||
/**
|
||||
* This struct has to be passed as an argument to GetPermissionsForApp.
|
||||
* |appId| has to be defined.
|
||||
@ -266,7 +271,15 @@ private:
|
||||
* specific app.
|
||||
* @param arg has to be an instance of GetPermissionsForAppStruct.
|
||||
*/
|
||||
static PLDHashOperator GetPermissionsForApp(nsPermissionManager::PermissionHashKey* entry, void* arg);
|
||||
static PLDHashOperator
|
||||
GetPermissionsForApp(PermissionHashKey* entry, void* arg);
|
||||
|
||||
/**
|
||||
* This method restores an app's permissions when its session ends.
|
||||
*/
|
||||
static PLDHashOperator
|
||||
RemoveExpiredPermissionsForAppEnumerator(PermissionHashKey* entry,
|
||||
void* nonused);
|
||||
|
||||
nsCOMPtr<nsIObserverService> mObserverService;
|
||||
nsCOMPtr<nsIIDNService> mIDNService;
|
||||
@ -283,6 +296,13 @@ private:
|
||||
// An array to store the strings identifying the different types.
|
||||
nsTArray<nsCString> mTypeArray;
|
||||
|
||||
// A list of struct for counting applications
|
||||
struct ApplicationCounter {
|
||||
uint32_t mAppId;
|
||||
uint32_t mCounter;
|
||||
};
|
||||
nsTArray<ApplicationCounter> mAppIdRefcounts;
|
||||
|
||||
// Initially, |false|. Set to |true| once shutdown has started, to avoid
|
||||
// reopening the database.
|
||||
bool mIsShuttingDown;
|
||||
|
@ -36,7 +36,7 @@ interface nsIObserver;
|
||||
interface nsIPrincipal;
|
||||
interface nsIDOMWindow;
|
||||
|
||||
[scriptable, uuid(ad79e135-6904-4734-8137-a511016d2723)]
|
||||
[scriptable, uuid(6c68cd87-4569-4695-8bc8-ad609f624b96)]
|
||||
interface nsIPermissionManager : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -173,6 +173,16 @@ interface nsIPermissionManager : nsISupports
|
||||
uint32_t testExactPermissionFromPrincipal(in nsIPrincipal principal,
|
||||
in string type);
|
||||
|
||||
/**
|
||||
* Increment or decrement our "refcount" of an app id.
|
||||
*
|
||||
* We use this refcount to determine an app's lifetime. When an app's
|
||||
* refcount goes to 0, we clear the permissions given to the app which are
|
||||
* set to expire at the end of its session.
|
||||
*/
|
||||
void addrefAppId(in unsigned long appId);
|
||||
void releaseAppId(in unsigned long appId);
|
||||
|
||||
/**
|
||||
* Allows enumeration of all stored permissions
|
||||
* @return an nsISimpleEnumerator interface that allows access to
|
||||
|
Loading…
Reference in New Issue
Block a user