зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1180088 - Use origin-based permission check on parent side for signed packaged web app. r=kanru.
This commit is contained in:
Родитель
02cb32707b
Коммит
9fe43dfb43
|
@ -97,6 +97,8 @@
|
||||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||||
#include "mozilla/WebBrowserPersistLocalDocument.h"
|
#include "mozilla/WebBrowserPersistLocalDocument.h"
|
||||||
|
|
||||||
|
#include "nsPrincipal.h"
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
#include "nsXULPopupManager.h"
|
#include "nsXULPopupManager.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -278,13 +280,20 @@ nsFrameLoader::LoadURI(nsIURI* aURI)
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsFrameLoader::SwitchProcessAndLoadURI(nsIURI* aURI)
|
nsFrameLoader::SwitchProcessAndLoadURI(nsIURI* aURI, const nsACString& aPackageId)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIURI> URIToLoad = aURI;
|
nsCOMPtr<nsIURI> URIToLoad = aURI;
|
||||||
RefPtr<TabParent> tp = nullptr;
|
RefPtr<TabParent> tp = nullptr;
|
||||||
|
|
||||||
|
nsCString signedPkgOrigin;
|
||||||
|
if (!aPackageId.IsEmpty()) {
|
||||||
|
// Only when aPackageId is not empty would signed package origin
|
||||||
|
// be meaningful.
|
||||||
|
nsPrincipal::GetOriginForURI(aURI, signedPkgOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
MutableTabContext context;
|
MutableTabContext context;
|
||||||
nsresult rv = GetNewTabContext(&context);
|
nsresult rv = GetNewTabContext(&context, signedPkgOrigin, aPackageId);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<Element> ownerElement = mOwnerContent;
|
nsCOMPtr<Element> ownerElement = mOwnerContent;
|
||||||
|
@ -3031,7 +3040,9 @@ nsFrameLoader::MaybeUpdatePrimaryTabParent(TabParentChange aChange)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext)
|
nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
|
||||||
|
const nsACString& aSignedPkgOriginNoSuffix,
|
||||||
|
const nsACString& aPackageId)
|
||||||
{
|
{
|
||||||
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
||||||
nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
|
nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
|
||||||
|
@ -3051,7 +3062,11 @@ nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext)
|
||||||
}
|
}
|
||||||
attrs.mAppId = appId;
|
attrs.mAppId = appId;
|
||||||
|
|
||||||
bool tabContextUpdated = aTabContext->SetTabContext(ownApp, containingApp, attrs);
|
// Populate packageId to signedPkg.
|
||||||
|
attrs.mSignedPkg = NS_ConvertUTF8toUTF16(aPackageId);
|
||||||
|
|
||||||
|
bool tabContextUpdated = aTabContext->SetTabContext(ownApp, containingApp,
|
||||||
|
attrs, aSignedPkgOriginNoSuffix);
|
||||||
NS_ENSURE_STATE(tabContextUpdated);
|
NS_ENSURE_STATE(tabContextUpdated);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
@ -318,7 +318,9 @@ private:
|
||||||
|
|
||||||
void InitializeBrowserAPI();
|
void InitializeBrowserAPI();
|
||||||
|
|
||||||
nsresult GetNewTabContext(mozilla::dom::MutableTabContext* aTabContext);
|
nsresult GetNewTabContext(mozilla::dom::MutableTabContext* aTabContext,
|
||||||
|
const nsACString& aSignedPkgNoSuffix = EmptyCString(),
|
||||||
|
const nsACString& aPackageId = EmptyCString());
|
||||||
|
|
||||||
enum TabParentChange {
|
enum TabParentChange {
|
||||||
eTabParentRemoved,
|
eTabParentRemoved,
|
||||||
|
|
|
@ -16,7 +16,7 @@ interface nsIDOMElement;
|
||||||
interface nsITabParent;
|
interface nsITabParent;
|
||||||
interface nsILoadContext;
|
interface nsILoadContext;
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(c6e00815-b7a1-4544-b309-a85b86cb1747)]
|
[scriptable, builtinclass, uuid(1645af04-1bc7-4363-8f2c-eb9679220ab1)]
|
||||||
interface nsIFrameLoader : nsISupports
|
interface nsIFrameLoader : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -52,10 +52,11 @@ interface nsIFrameLoader : nsISupports
|
||||||
/**
|
/**
|
||||||
* Loads the specified URI in this frame but using a different process.
|
* Loads the specified URI in this frame but using a different process.
|
||||||
* Behaves identically to loadURI, except that this method only works
|
* Behaves identically to loadURI, except that this method only works
|
||||||
* with remote frame.
|
* with remote frame. For a signed package, we need to specifiy the
|
||||||
|
* package identifier.
|
||||||
* Throws an exception with non-remote frames.
|
* Throws an exception with non-remote frames.
|
||||||
*/
|
*/
|
||||||
void switchProcessAndLoadURI(in nsIURI aURI);
|
void switchProcessAndLoadURI(in nsIURI aURI, in ACString aPackageId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Puts the frameloader in prerendering mode.
|
* Puts the frameloader in prerendering mode.
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
.QueryInterface(Ci.nsIFrameLoaderOwner)
|
.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||||
.frameLoader;
|
.frameLoader;
|
||||||
var uri = SpecialPowers.Services.io.newURI(url, null, null);
|
var uri = SpecialPowers.Services.io.newURI(url, null, null);
|
||||||
fl.switchProcessAndLoadURI(uri);
|
fl.switchProcessAndLoadURI(uri, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function runTest() {
|
function runTest() {
|
||||||
|
|
|
@ -35,6 +35,12 @@ class nsIPrincipal;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
#if DEUBG
|
||||||
|
#define LOG(args...) printf_stderr(args)
|
||||||
|
#else
|
||||||
|
#define LOG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_CHILD_PERMISSIONS
|
#ifdef MOZ_CHILD_PERMISSIONS
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -118,11 +124,52 @@ AssertAppStatus(PBrowserParent* aActor,
|
||||||
return CheckAppStatusHelper(app, aStatus);
|
return CheckAppStatusHelper(app, aStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A general purpose helper function to check permission against the origin
|
||||||
|
// rather than mozIApplication.
|
||||||
|
static bool
|
||||||
|
CheckOriginPermission(const nsACString& aOrigin, const char* aPermission)
|
||||||
|
{
|
||||||
|
LOG("CheckOriginPermission: %s, %s\n", nsCString(aOrigin).get(), aPermission);
|
||||||
|
|
||||||
|
nsIScriptSecurityManager *securityManager =
|
||||||
|
nsContentUtils::GetSecurityManager();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
|
securityManager->CreateCodebasePrincipalFromOrigin(aOrigin,
|
||||||
|
getter_AddRefs(principal));
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
||||||
|
NS_ENSURE_TRUE(permMgr, false);
|
||||||
|
|
||||||
|
uint32_t perm;
|
||||||
|
nsresult rv = permMgr->TestExactPermissionFromPrincipal(principal, aPermission, &perm);
|
||||||
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
|
|
||||||
|
LOG("Permission %s for %s: %d\n", aPermission, nsCString(aOrigin).get(), perm);
|
||||||
|
return nsIPermissionManager::ALLOW_ACTION == perm;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AssertAppProcess(TabContext& aContext,
|
AssertAppProcess(TabContext& aContext,
|
||||||
AssertAppProcessType aType,
|
AssertAppProcessType aType,
|
||||||
const char* aCapability)
|
const char* aCapability)
|
||||||
{
|
{
|
||||||
|
const mozilla::OriginAttributes& attr = aContext.OriginAttributesRef();
|
||||||
|
nsCString suffix;
|
||||||
|
attr.CreateSuffix(suffix);
|
||||||
|
|
||||||
|
if (!aContext.SignedPkgOriginNoSuffix().IsEmpty()) {
|
||||||
|
LOG("TabContext owning signed package origin: %s, originAttr; %s\n",
|
||||||
|
nsCString(aContext.SignedPkgOriginNoSuffix()).get(),
|
||||||
|
suffix.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a origin-based permission check if the TabContext owns a signed package.
|
||||||
|
if (!aContext.SignedPkgOriginNoSuffix().IsEmpty() &&
|
||||||
|
(ASSERT_APP_HAS_PERMISSION == aType || ASSERT_APP_PROCESS_PERMISSION == aType)) {
|
||||||
|
nsCString origin = aContext.SignedPkgOriginNoSuffix() + suffix;
|
||||||
|
return CheckOriginPermission(origin, aCapability);
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<mozIApplication> app = aContext.GetOwnOrContainingApp();
|
nsCOMPtr<mozIApplication> app = aContext.GetOwnOrContainingApp();
|
||||||
return CheckAppTypeHelper(app, aType, aCapability, aContext.IsBrowserElement());
|
return CheckAppTypeHelper(app, aType, aCapability, aContext.IsBrowserElement());
|
||||||
|
|
|
@ -37,6 +37,11 @@ struct FrameIPCTabContext
|
||||||
|
|
||||||
// The ID of the app containing this app/browser frame, if applicable.
|
// The ID of the app containing this app/browser frame, if applicable.
|
||||||
uint32_t frameOwnerAppId;
|
uint32_t frameOwnerAppId;
|
||||||
|
|
||||||
|
// The origin without originAttribute suffix for a signed package.
|
||||||
|
// This value would be empty if the TabContext doesn't own a signed
|
||||||
|
// package.
|
||||||
|
nsCString signedPkgOriginNoSuffix;
|
||||||
};
|
};
|
||||||
|
|
||||||
// IPCTabContext is an analog to mozilla::dom::TabContext. Both specify an
|
// IPCTabContext is an analog to mozilla::dom::TabContext. Both specify an
|
||||||
|
|
|
@ -158,11 +158,17 @@ TabContext::OriginAttributesRef() const
|
||||||
return mOriginAttributes;
|
return mOriginAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nsACString&
|
||||||
|
TabContext::SignedPkgOriginNoSuffix() const
|
||||||
|
{
|
||||||
|
return mSignedPkgOriginNoSuffix;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TabContext::SetTabContext(mozIApplication* aOwnApp,
|
TabContext::SetTabContext(mozIApplication* aOwnApp,
|
||||||
mozIApplication* aAppFrameOwnerApp,
|
mozIApplication* aAppFrameOwnerApp,
|
||||||
const OriginAttributes& aOriginAttributes)
|
const OriginAttributes& aOriginAttributes,
|
||||||
|
const nsACString& aSignedPkgOriginNoSuffix)
|
||||||
{
|
{
|
||||||
NS_ENSURE_FALSE(mInitialized, false);
|
NS_ENSURE_FALSE(mInitialized, false);
|
||||||
|
|
||||||
|
@ -192,6 +198,7 @@ TabContext::SetTabContext(mozIApplication* aOwnApp,
|
||||||
mContainingAppId = containingAppId;
|
mContainingAppId = containingAppId;
|
||||||
mOwnApp = aOwnApp;
|
mOwnApp = aOwnApp;
|
||||||
mContainingApp = aAppFrameOwnerApp;
|
mContainingApp = aAppFrameOwnerApp;
|
||||||
|
mSignedPkgOriginNoSuffix = aSignedPkgOriginNoSuffix;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +207,9 @@ TabContext::AsIPCTabContext() const
|
||||||
{
|
{
|
||||||
nsAutoCString originSuffix;
|
nsAutoCString originSuffix;
|
||||||
mOriginAttributes.CreateSuffix(originSuffix);
|
mOriginAttributes.CreateSuffix(originSuffix);
|
||||||
return IPCTabContext(FrameIPCTabContext(originSuffix, mContainingAppId));
|
return IPCTabContext(FrameIPCTabContext(originSuffix,
|
||||||
|
mContainingAppId,
|
||||||
|
mSignedPkgOriginNoSuffix));
|
||||||
}
|
}
|
||||||
|
|
||||||
static already_AddRefed<mozIApplication>
|
static already_AddRefed<mozIApplication>
|
||||||
|
@ -221,6 +230,7 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
||||||
uint32_t containingAppId = NO_APP_ID;
|
uint32_t containingAppId = NO_APP_ID;
|
||||||
OriginAttributes originAttributes = OriginAttributes();
|
OriginAttributes originAttributes = OriginAttributes();
|
||||||
nsAutoCString originSuffix;
|
nsAutoCString originSuffix;
|
||||||
|
nsAutoCString signedPkgOriginNoSuffix;
|
||||||
|
|
||||||
const IPCTabContextUnion& contextUnion = aParams.contextUnion();
|
const IPCTabContextUnion& contextUnion = aParams.contextUnion();
|
||||||
switch(contextUnion.type()) {
|
switch(contextUnion.type()) {
|
||||||
|
@ -276,6 +286,7 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
||||||
contextUnion.get_FrameIPCTabContext();
|
contextUnion.get_FrameIPCTabContext();
|
||||||
|
|
||||||
containingAppId = ipcContext.frameOwnerAppId();
|
containingAppId = ipcContext.frameOwnerAppId();
|
||||||
|
signedPkgOriginNoSuffix = ipcContext.signedPkgOriginNoSuffix();
|
||||||
originSuffix = ipcContext.originSuffix();
|
originSuffix = ipcContext.originSuffix();
|
||||||
originAttributes.PopulateFromSuffix(originSuffix);
|
originAttributes.PopulateFromSuffix(originSuffix);
|
||||||
break;
|
break;
|
||||||
|
@ -305,7 +316,8 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
||||||
bool rv;
|
bool rv;
|
||||||
rv = mTabContext.SetTabContext(ownApp,
|
rv = mTabContext.SetTabContext(ownApp,
|
||||||
containingApp,
|
containingApp,
|
||||||
originAttributes);
|
originAttributes,
|
||||||
|
signedPkgOriginNoSuffix);
|
||||||
if (!rv) {
|
if (!rv) {
|
||||||
mInvalidReason = "Couldn't initialize TabContext.";
|
mInvalidReason = "Couldn't initialize TabContext.";
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,12 @@ public:
|
||||||
*/
|
*/
|
||||||
const OriginAttributes& OriginAttributesRef() const;
|
const OriginAttributes& OriginAttributesRef() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the origin associated with the tab (w/o suffix) if this tab owns
|
||||||
|
* a signed packaged content.
|
||||||
|
*/
|
||||||
|
const nsACString& SignedPkgOriginNoSuffix() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class MaybeInvalidTabContext;
|
friend class MaybeInvalidTabContext;
|
||||||
|
|
||||||
|
@ -136,7 +142,8 @@ protected:
|
||||||
*/
|
*/
|
||||||
bool SetTabContext(mozIApplication* aOwnApp,
|
bool SetTabContext(mozIApplication* aOwnApp,
|
||||||
mozIApplication* aAppFrameOwnerApp,
|
mozIApplication* aAppFrameOwnerApp,
|
||||||
const OriginAttributes& aOriginAttributes);
|
const OriginAttributes& aOriginAttributes,
|
||||||
|
const nsACString& aSignedPkgOriginNoSuffix);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
@ -167,6 +174,13 @@ private:
|
||||||
*/
|
*/
|
||||||
OriginAttributes mOriginAttributes;
|
OriginAttributes mOriginAttributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signed package origin without suffix. Since the signed packaged
|
||||||
|
* web content is always loaded in a separate process, it makes sense
|
||||||
|
* that we store this immutable value in TabContext. If the TabContext
|
||||||
|
* doesn't own a signed package, this value would be empty.
|
||||||
|
*/
|
||||||
|
nsCString mSignedPkgOriginNoSuffix;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,11 +198,13 @@ public:
|
||||||
|
|
||||||
bool SetTabContext(mozIApplication* aOwnApp,
|
bool SetTabContext(mozIApplication* aOwnApp,
|
||||||
mozIApplication* aAppFrameOwnerApp,
|
mozIApplication* aAppFrameOwnerApp,
|
||||||
const OriginAttributes& aOriginAttributes)
|
const OriginAttributes& aOriginAttributes,
|
||||||
|
const nsACString& aSignedPkgOriginNoSuffix = EmptyCString())
|
||||||
{
|
{
|
||||||
return TabContext::SetTabContext(aOwnApp,
|
return TabContext::SetTabContext(aOwnApp,
|
||||||
aAppFrameOwnerApp,
|
aAppFrameOwnerApp,
|
||||||
aOriginAttributes);
|
aOriginAttributes,
|
||||||
|
aSignedPkgOriginNoSuffix);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -518,7 +518,8 @@ TabParent::ShouldSwitchProcess(nsIChannel* aChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TabParent::OnStartSignedPackageRequest(nsIChannel* aChannel)
|
TabParent::OnStartSignedPackageRequest(nsIChannel* aChannel,
|
||||||
|
const nsACString& aPackageId)
|
||||||
{
|
{
|
||||||
if (!ShouldSwitchProcess(aChannel)) {
|
if (!ShouldSwitchProcess(aChannel)) {
|
||||||
return;
|
return;
|
||||||
|
@ -537,7 +538,7 @@ TabParent::OnStartSignedPackageRequest(nsIChannel* aChannel)
|
||||||
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||||
NS_ENSURE_TRUE_VOID(frameLoader);
|
NS_ENSURE_TRUE_VOID(frameLoader);
|
||||||
|
|
||||||
nsresult rv = frameLoader->SwitchProcessAndLoadURI(uri);
|
nsresult rv = frameLoader->SwitchProcessAndLoadURI(uri, aPackageId);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
NS_WARNING("Failed to switch process.");
|
NS_WARNING("Failed to switch process.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,7 +456,8 @@ public:
|
||||||
|
|
||||||
// Called by HttpChannelParent. The function may use a new process to
|
// Called by HttpChannelParent. The function may use a new process to
|
||||||
// reload the URI associated with the given channel.
|
// reload the URI associated with the given channel.
|
||||||
void OnStartSignedPackageRequest(nsIChannel* aChannel);
|
void OnStartSignedPackageRequest(nsIChannel* aChannel,
|
||||||
|
const nsACString& aPackageId);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ReceiveMessage(const nsString& aMessage,
|
bool ReceiveMessage(const nsString& aMessage,
|
||||||
|
|
|
@ -1057,7 +1057,7 @@ NS_IMETHODIMP
|
||||||
HttpChannelParent::OnStartSignedPackageRequest(const nsACString& aPackageId)
|
HttpChannelParent::OnStartSignedPackageRequest(const nsACString& aPackageId)
|
||||||
{
|
{
|
||||||
if (mTabParent) {
|
if (mTabParent) {
|
||||||
mTabParent->OnStartSignedPackageRequest(mChannel);
|
mTabParent->OnStartSignedPackageRequest(mChannel, aPackageId);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче