mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 802366 - The main event: Let a browser process inherit its app's id. r=bz,cjones
The main bug fixed here is that in half of our interfaces, we use "is browser frame/element" to mean "browser or app", and in the other half, we use it to mean "is browser not app". There's a related, functional bug also fixed here, which is that a browser process doesn't inherit its parent's app-id. This causes problems e.g. for IndexedDB: If a browser inside an app uses IndexedDB, the DB should have the app's app-id. I also modified Tab{Parent,Child} and nsFrameLoader to call "app" "ownOrContainingApp", to emphasize that we might have inherited the app from a parent process. I left nsIDocShell::appId alone, because changing that would have necessitated changing nsILoadGroup and therefore a /lot/ of users in Necko; it's also not clear it would have clarified anything in those cases.
This commit is contained in:
parent
1063cbe1b5
commit
785d3c9b2f
@ -8359,7 +8359,7 @@ HasCrossProcessParent(nsIDocument* aDocument)
|
||||
if (!docShell) {
|
||||
return false;
|
||||
}
|
||||
return docShell->GetIsContentBoundary();
|
||||
return docShell->GetIsBrowserOrApp();
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -944,7 +944,7 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size)
|
||||
EnsureMessageManager();
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (OwnerIsBrowserFrame() && os && !mRemoteBrowserInitialized) {
|
||||
if (OwnerIsBrowserOrAppFrame() && os && !mRemoteBrowserInitialized) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
|
||||
"remote-browser-frame-shown", NULL);
|
||||
mRemoteBrowserInitialized = true;
|
||||
@ -1393,25 +1393,23 @@ nsFrameLoader::SetOwnerContent(Element* aContent)
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsBrowserFrame()
|
||||
nsFrameLoader::OwnerIsBrowserOrAppFrame()
|
||||
{
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
bool isBrowser = false;
|
||||
if (browserFrame) {
|
||||
browserFrame->GetReallyIsBrowser(&isBrowser);
|
||||
}
|
||||
return isBrowser;
|
||||
return browserFrame ? browserFrame->GetReallyIsBrowserOrApp() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsAppFrame()
|
||||
{
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
||||
bool isApp = false;
|
||||
if (browserFrame) {
|
||||
browserFrame->GetReallyIsApp(&isApp);
|
||||
}
|
||||
return isApp;
|
||||
return browserFrame ? browserFrame->GetReallyIsApp() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::OwnerIsBrowserFrame()
|
||||
{
|
||||
return OwnerIsBrowserOrAppFrame() && !OwnerIsAppFrame();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1424,6 +1422,50 @@ nsFrameLoader::GetOwnerAppManifestURL(nsAString& aOut)
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
nsFrameLoader::GetOwnApp()
|
||||
{
|
||||
nsAutoString manifest;
|
||||
GetOwnerAppManifestURL(manifest);
|
||||
if (manifest.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(appsService, nullptr);
|
||||
|
||||
nsCOMPtr<mozIDOMApplication> domApp;
|
||||
appsService->GetAppByManifestURL(manifest, getter_AddRefs(domApp));
|
||||
|
||||
nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
|
||||
MOZ_ASSERT_IF(domApp, app);
|
||||
return app.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
nsFrameLoader::GetContainingApp()
|
||||
{
|
||||
// See if our owner content's principal has an associated app.
|
||||
uint32_t appId = mOwnerContent->NodePrincipal()->GetAppId();
|
||||
MOZ_ASSERT(appId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||
|
||||
if (appId == nsIScriptSecurityManager::NO_APP_ID ||
|
||||
appId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(appsService, nullptr);
|
||||
|
||||
nsCOMPtr<mozIDOMApplication> domApp;
|
||||
appsService->GetAppByLocalId(appId, getter_AddRefs(domApp));
|
||||
MOZ_ASSERT(domApp);
|
||||
|
||||
nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
|
||||
MOZ_ASSERT_IF(domApp, app);
|
||||
return app.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
nsFrameLoader::ShouldUseRemoteProcess()
|
||||
{
|
||||
@ -1440,7 +1482,7 @@ nsFrameLoader::ShouldUseRemoteProcess()
|
||||
|
||||
// If we're an <iframe mozbrowser> and we don't have a "remote" attribute,
|
||||
// fall back to the default.
|
||||
if (OwnerIsBrowserFrame() &&
|
||||
if (OwnerIsBrowserOrAppFrame() &&
|
||||
!mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::Remote)) {
|
||||
|
||||
return Preferences::GetBool("dom.ipc.browser_frames.oop_by_default", false);
|
||||
@ -1448,7 +1490,7 @@ nsFrameLoader::ShouldUseRemoteProcess()
|
||||
|
||||
// Otherwise, we're remote if we have "remote=true" and we're either a
|
||||
// browser frame or a XUL element.
|
||||
return (OwnerIsBrowserFrame() ||
|
||||
return (OwnerIsBrowserOrAppFrame() ||
|
||||
mOwnerContent->GetNameSpaceID() == kNameSpaceID_XUL) &&
|
||||
mOwnerContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsGkAtoms::Remote,
|
||||
@ -1495,24 +1537,6 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
||||
if (OwnerIsBrowserFrame()) {
|
||||
nsAutoString manifest;
|
||||
GetOwnerAppManifestURL(manifest);
|
||||
if (!manifest.IsEmpty()) {
|
||||
nsCOMPtr<nsIAppsService> appsService =
|
||||
do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
if (!appsService) {
|
||||
NS_ERROR("Apps Service is not available!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint32_t appId;
|
||||
appsService->GetAppLocalIdByManifestURL(manifest, &appId);
|
||||
|
||||
mDocShell->SetAppId(appId);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mNetworkCreated) {
|
||||
nsCOMPtr<nsIDocShellHistory> history = do_QueryInterface(mDocShell);
|
||||
if (history) {
|
||||
@ -1614,9 +1638,34 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
|
||||
EnsureMessageManager();
|
||||
|
||||
if (OwnerIsBrowserFrame()) {
|
||||
mDocShell->SetIsBrowserElement();
|
||||
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_ENSURE_SUCCESS(ownApp->GetLocalId(&ownAppId), NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
mDocShell->SetIsApp(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_ENSURE_SUCCESS(containingApp->GetLocalId(&containingAppId),
|
||||
NS_ERROR_FAILURE);
|
||||
}
|
||||
mDocShell->SetIsBrowserInsideApp(containingAppId);
|
||||
}
|
||||
|
||||
if (OwnerIsBrowserOrAppFrame()) {
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
|
||||
@ -1948,7 +1997,7 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(parentAsWebNav));
|
||||
|
||||
// <iframe mozbrowser> gets to skip these checks.
|
||||
if (!OwnerIsBrowserFrame()) {
|
||||
if (!OwnerIsBrowserOrAppFrame()) {
|
||||
int32_t parentType;
|
||||
parentAsItem->GetItemType(&parentType);
|
||||
|
||||
@ -1984,35 +2033,18 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isBrowserElement = false;
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
if (OwnerIsBrowserFrame()) {
|
||||
isBrowserElement = true;
|
||||
|
||||
nsAutoString manifest;
|
||||
GetOwnerAppManifestURL(manifest);
|
||||
if (!manifest.IsEmpty()) {
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
if (!appsService) {
|
||||
NS_ERROR("Apps Service is not available!");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIDOMApplication> domApp;
|
||||
appsService->GetAppByManifestURL(manifest, getter_AddRefs(domApp));
|
||||
// If the frame is actually an app, we should not mark it as a
|
||||
// browser. This is to identify the data store: since <app>s
|
||||
// and <browser>s-within-<app>s have different stores, we want
|
||||
// to ensure the <app> uses its store, not the one for its
|
||||
// <browser>s.
|
||||
app = do_QueryInterface(domApp);
|
||||
if (app) {
|
||||
isBrowserElement = false;
|
||||
}
|
||||
}
|
||||
MutableTabContext context;
|
||||
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
||||
nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
|
||||
if (ownApp) {
|
||||
context.SetTabContextForAppFrame(ownApp, containingApp);
|
||||
} else if (OwnerIsBrowserFrame()) {
|
||||
// The |else| above is unnecessary; OwnerIsBrowserFrame() implies !ownApp.
|
||||
context.SetTabContextForBrowserFrame(containingApp);
|
||||
}
|
||||
|
||||
if ((mRemoteBrowser = ContentParent::CreateBrowser(app, isBrowserElement))) {
|
||||
mRemoteBrowser = ContentParent::CreateBrowserOrApp(context);
|
||||
if (mRemoteBrowser) {
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mOwnerContent);
|
||||
mRemoteBrowser->SetOwnerElement(element);
|
||||
|
||||
@ -2322,7 +2354,7 @@ nsFrameLoader::EnsureMessageManager()
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mIsTopLevelContent && !OwnerIsBrowserFrame() && !mRemoteFrame) {
|
||||
if (!mIsTopLevelContent && !OwnerIsBrowserOrAppFrame() && !mRemoteFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ class nsITabParent;
|
||||
class nsIDocShellTreeItem;
|
||||
class nsIDocShellTreeOwner;
|
||||
class nsIDocShellTreeNode;
|
||||
class mozIApplication;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -313,9 +314,9 @@ private:
|
||||
/**
|
||||
* Is this a frameloader for a bona fide <iframe mozbrowser> or
|
||||
* <iframe mozapp>? (I.e., does the frame return true for
|
||||
* nsIMozBrowserFrame::GetReallyIsBrowser()?)
|
||||
* nsIMozBrowserFrame::GetReallyIsBrowserOrApp()?)
|
||||
*/
|
||||
bool OwnerIsBrowserFrame();
|
||||
bool OwnerIsBrowserOrAppFrame();
|
||||
|
||||
/**
|
||||
* Is this a frameloader for a bona fide <iframe mozapp>? (I.e., does the
|
||||
@ -323,12 +324,29 @@ private:
|
||||
*/
|
||||
bool OwnerIsAppFrame();
|
||||
|
||||
/**
|
||||
* Is this a frame loader for a bona fide <iframe mozbrowser>?
|
||||
*/
|
||||
bool OwnerIsBrowserFrame();
|
||||
|
||||
/**
|
||||
* Get our owning element's app manifest URL, or return the empty string if
|
||||
* our owning element doesn't have an app manifest URL.
|
||||
*/
|
||||
void GetOwnerAppManifestURL(nsAString& aOut);
|
||||
|
||||
/**
|
||||
* Get the app for our frame. This is the app whose manifest is returned by
|
||||
* GetOwnerAppManifestURL.
|
||||
*/
|
||||
already_AddRefed<mozIApplication> GetOwnApp();
|
||||
|
||||
/**
|
||||
* Get the app which contains this frame. This is the app associated with
|
||||
* the frame element's principal.
|
||||
*/
|
||||
already_AddRefed<mozIApplication> GetContainingApp();
|
||||
|
||||
/**
|
||||
* If we are an IPC frame, set mRemoteFrame. Otherwise, create and
|
||||
* initialize mDocShell.
|
||||
|
@ -97,14 +97,15 @@ nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
|
||||
mDelayedDisconnect(false), mOwner(aOwner), mChromeMessageManager(aChrome)
|
||||
{
|
||||
|
||||
// If owner corresponds to an <iframe mozbrowser>, we'll have to tweak our
|
||||
// PreHandleEvent implementation.
|
||||
// If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
|
||||
// have to tweak our PreHandleEvent implementation.
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
|
||||
bool isBrowser = false;
|
||||
if (browserFrame) {
|
||||
browserFrame->GetReallyIsBrowser(&isBrowser);
|
||||
mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp();
|
||||
}
|
||||
else {
|
||||
mIsBrowserOrAppFrame = false;
|
||||
}
|
||||
mIsBrowserFrame = isBrowser;
|
||||
}
|
||||
|
||||
nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
|
||||
@ -268,7 +269,7 @@ nsInProcessTabChildGlobal::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mCanHandle = true;
|
||||
|
||||
if (mIsBrowserFrame &&
|
||||
if (mIsBrowserOrAppFrame &&
|
||||
(!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) {
|
||||
if (mOwner) {
|
||||
nsPIDOMWindow* innerWindow = mOwner->OwnerDoc()->GetInnerWindow();
|
||||
|
@ -122,9 +122,10 @@ protected:
|
||||
bool mLoadingScript;
|
||||
bool mDelayedDisconnect;
|
||||
|
||||
// Is this the message manager for an in-process <iframe mozbrowser>? This
|
||||
// affects where events get sent, so it affects PreHandleEvent.
|
||||
bool mIsBrowserFrame;
|
||||
// Is this the message manager for an in-process <iframe mozbrowser> or
|
||||
// <iframe mozapp>? This affects where events get sent, so it affects
|
||||
// PreHandleEvent.
|
||||
bool mIsBrowserOrAppFrame;
|
||||
public:
|
||||
nsIContent* mOwner;
|
||||
nsFrameMessageManager* mChromeMessageManager;
|
||||
|
@ -1570,14 +1570,10 @@ nsEventStateManager::IsRemoteTarget(nsIContent* target) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// <frame/iframe mozbrowser>
|
||||
// <frame/iframe mozbrowser/mozapp>
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(target);
|
||||
if (browserFrame) {
|
||||
bool isBrowser = false;
|
||||
browserFrame->GetReallyIsBrowser(&isBrowser);
|
||||
if (isBrowser) {
|
||||
return !!TabParent::GetFrom(target);
|
||||
}
|
||||
if (browserFrame && browserFrame->GetReallyIsBrowserOrApp()) {
|
||||
return !!TabParent::GetFrom(target);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -278,8 +278,8 @@ nsGenericHTMLFrameElement::IsHTMLFocusable(bool aWithMouse,
|
||||
* needs to have the right attributes, and its creator must have the right
|
||||
* permissions.)
|
||||
*/
|
||||
nsresult
|
||||
nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aOut)
|
||||
/* [infallible] */ nsresult
|
||||
nsGenericHTMLFrameElement::GetReallyIsBrowserOrApp(bool *aOut)
|
||||
{
|
||||
*aOut = false;
|
||||
|
||||
@ -289,9 +289,9 @@ nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aOut)
|
||||
}
|
||||
|
||||
// Fail if this frame doesn't have the mozbrowser attribute.
|
||||
bool isBrowser = false;
|
||||
GetMozbrowser(&isBrowser);
|
||||
if (!isBrowser) {
|
||||
bool hasMozbrowser = false;
|
||||
GetMozbrowser(&hasMozbrowser);
|
||||
if (!hasMozbrowser) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -299,7 +299,7 @@ nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aOut)
|
||||
nsIPrincipal *principal = NodePrincipal();
|
||||
nsCOMPtr<nsIPermissionManager> permMgr =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
NS_ENSURE_STATE(permMgr);
|
||||
NS_ENSURE_TRUE(permMgr, NS_OK);
|
||||
|
||||
uint32_t permission = nsIPermissionManager::DENY_ACTION;
|
||||
nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission);
|
||||
@ -308,7 +308,7 @@ nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsGenericHTMLFrameElement::GetReallyIsApp(bool *aOut)
|
||||
{
|
||||
nsAutoString manifestURL;
|
||||
@ -324,9 +324,7 @@ nsGenericHTMLFrameElement::GetAppManifestURL(nsAString& aOut)
|
||||
aOut.Truncate();
|
||||
|
||||
// At the moment, you can't be an app without being a browser.
|
||||
bool isBrowser = false;
|
||||
GetReallyIsBrowser(&isBrowser);
|
||||
if (!isBrowser) {
|
||||
if (!nsIMozBrowserFrame::GetReallyIsBrowserOrApp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -334,7 +332,7 @@ nsGenericHTMLFrameElement::GetAppManifestURL(nsAString& aOut)
|
||||
nsIPrincipal *principal = NodePrincipal();
|
||||
nsCOMPtr<nsIPermissionManager> permMgr =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
NS_ENSURE_STATE(permMgr);
|
||||
NS_ENSURE_TRUE(permMgr, NS_OK);
|
||||
|
||||
uint32_t permission = nsIPermissionManager::DENY_ACTION;
|
||||
nsresult rv = permMgr->TestPermissionFromPrincipal(principal,
|
||||
@ -352,11 +350,10 @@ nsGenericHTMLFrameElement::GetAppManifestURL(nsAString& aOut)
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_STATE(appsService);
|
||||
NS_ENSURE_TRUE(appsService, NS_OK);
|
||||
|
||||
nsCOMPtr<mozIDOMApplication> app;
|
||||
appsService->GetAppByManifestURL(manifestURL, getter_AddRefs(app));
|
||||
|
||||
if (app) {
|
||||
aOut.Assign(manifestURL);
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ bool nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIRequest *request,
|
||||
parentDocShellItem) {
|
||||
|
||||
nsCOMPtr<nsIDocShell> curDocShell = do_QueryInterface(curDocShellItem);
|
||||
if (curDocShell && curDocShell->GetIsContentBoundary()) {
|
||||
if (curDocShell && curDocShell->GetIsBrowserOrApp()) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -730,6 +730,7 @@ nsDocShell::nsDocShell():
|
||||
mCharsetReloadState(eCharsetReloadInit),
|
||||
mChildOffset(0),
|
||||
mBusyFlags(BUSY_FLAGS_NONE),
|
||||
mFrameType(eFrameTypeRegular),
|
||||
mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
|
||||
mLoadType(0),
|
||||
mMarginWidth(-1),
|
||||
@ -767,7 +768,7 @@ nsDocShell::nsDocShell():
|
||||
#ifdef DEBUG
|
||||
mInEnsureScriptEnv(false),
|
||||
#endif
|
||||
mAppId(nsIScriptSecurityManager::NO_APP_ID),
|
||||
mOwnOrContainingAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID),
|
||||
mParentCharsetSource(0)
|
||||
{
|
||||
mHistoryID = ++gDocshellIDCounter;
|
||||
@ -2150,7 +2151,7 @@ nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFullscreenAllowed);
|
||||
|
||||
// Content boundaries have their mFullscreenAllowed retrieved from their
|
||||
// Browsers and apps have their mFullscreenAllowed retrieved from their
|
||||
// corresponding iframe in their parent upon creation.
|
||||
if (mFullscreenAllowed != CHECK_ATTRIBUTES) {
|
||||
*aFullscreenAllowed = (mFullscreenAllowed == PARENT_ALLOWS);
|
||||
@ -2160,9 +2161,9 @@ nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
|
||||
// Assume false until we determine otherwise...
|
||||
*aFullscreenAllowed = false;
|
||||
|
||||
// For non-content boundaries, check that the enclosing iframe element
|
||||
// For non-browsers/apps, check that the enclosing iframe element
|
||||
// has the allowfullscreen attribute set to true. If any ancestor
|
||||
// iframe does not have allowfullscreen=true, then fullscreen is
|
||||
// iframe does not have mozallowfullscreen=true, then fullscreen is
|
||||
// prohibited.
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(GetAsSupports(this));
|
||||
if (!win) {
|
||||
@ -2199,7 +2200,7 @@ nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed)
|
||||
{
|
||||
if (!nsIDocShell::GetIsContentBoundary()) {
|
||||
if (!nsIDocShell::GetIsBrowserOrApp()) {
|
||||
// Only allow setting of fullscreenAllowed on content/process boundaries.
|
||||
// At non-boundaries the fullscreenAllowed attribute is calculated based on
|
||||
// whether all enclosing frames have the "mozFullscreenAllowed" attribute
|
||||
@ -2811,7 +2812,7 @@ nsDocShell::GetSameTypeParent(nsIDocShellTreeItem ** aParent)
|
||||
NS_ENSURE_ARG_POINTER(aParent);
|
||||
*aParent = nullptr;
|
||||
|
||||
if (mIsBrowserFrame) {
|
||||
if (nsIDocShell::GetIsBrowserOrApp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2933,19 +2934,11 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetDS && accessingDS) {
|
||||
bool targetInBrowser = false, accessingInBrowser = false;
|
||||
targetDS->GetIsInBrowserElement(&targetInBrowser);
|
||||
accessingDS->GetIsInBrowserElement(&accessingInBrowser);
|
||||
|
||||
uint32_t targetAppId = 0, accessingAppId = 0;
|
||||
targetDS->GetAppId(&targetAppId);
|
||||
accessingDS->GetAppId(&accessingAppId);
|
||||
|
||||
if (targetInBrowser != accessingInBrowser ||
|
||||
targetAppId != accessingAppId) {
|
||||
return false;
|
||||
}
|
||||
if (targetDS && accessingDS &&
|
||||
(targetDS->GetIsInBrowserElement() !=
|
||||
accessingDS->GetIsInBrowserElement() ||
|
||||
targetDS->GetAppId() != accessingDS->GetAppId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> accessingRoot;
|
||||
@ -5229,7 +5222,7 @@ nsDocShell::SetIsActive(bool aIsActive)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!docshell->GetIsContentBoundary()) {
|
||||
if (!docshell->GetIsBrowserOrApp()) {
|
||||
docshell->SetIsActive(aIsActive);
|
||||
}
|
||||
}
|
||||
@ -12311,19 +12304,52 @@ nsDocShell::GetCanExecuteScripts(bool *aResult)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetIsBrowserElement()
|
||||
nsDocShell::SetIsApp(uint32_t aOwnAppId)
|
||||
{
|
||||
if (mIsBrowserFrame) {
|
||||
NS_ERROR("You should not call SetIsBrowserElement() more than once.");
|
||||
return NS_OK;
|
||||
mOwnOrContainingAppId = aOwnAppId;
|
||||
if (aOwnAppId != nsIScriptSecurityManager::NO_APP_ID &&
|
||||
aOwnAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||
mFrameType = eFrameTypeApp;
|
||||
} else {
|
||||
mFrameType = eFrameTypeRegular;
|
||||
}
|
||||
|
||||
mIsBrowserFrame = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
os->NotifyObservers(GetAsSupports(this),
|
||||
"docshell-marked-as-browser-frame", NULL);
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetIsBrowserInsideApp(uint32_t aContainingAppId)
|
||||
{
|
||||
mOwnOrContainingAppId = aContainingAppId;
|
||||
mFrameType = eFrameTypeBrowser;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsBrowserElement(bool* aIsBrowser)
|
||||
{
|
||||
*aIsBrowser = (mFrameType == eFrameTypeBrowser);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsApp(bool* aIsApp)
|
||||
{
|
||||
*aIsApp = (mFrameType == eFrameTypeApp);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsBrowserOrApp(bool* aIsBrowserOrApp)
|
||||
{
|
||||
switch (mFrameType) {
|
||||
case eFrameTypeRegular:
|
||||
*aIsBrowserOrApp = false;
|
||||
break;
|
||||
case eFrameTypeBrowser:
|
||||
case eFrameTypeApp:
|
||||
*aIsBrowserOrApp = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -12332,10 +12358,8 @@ nsDocShell::SetIsBrowserElement()
|
||||
nsDocShell::FrameType
|
||||
nsDocShell::GetInheritedFrameType()
|
||||
{
|
||||
FrameType type = GetFrameType();
|
||||
|
||||
if (type != eFrameTypeRegular) {
|
||||
return type;
|
||||
if (mFrameType != eFrameTypeRegular) {
|
||||
return mFrameType;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
|
||||
@ -12349,46 +12373,6 @@ nsDocShell::GetInheritedFrameType()
|
||||
return static_cast<nsDocShell*>(parent.get())->GetInheritedFrameType();
|
||||
}
|
||||
|
||||
nsDocShell::FrameType
|
||||
nsDocShell::GetFrameType()
|
||||
{
|
||||
if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
return eFrameTypeApp;
|
||||
}
|
||||
|
||||
return mIsBrowserFrame ? eFrameTypeBrowser : eFrameTypeRegular;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsBrowserElement(bool* aIsBrowser)
|
||||
{
|
||||
*aIsBrowser = (GetFrameType() == eFrameTypeBrowser);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsApp(bool* aIsApp)
|
||||
{
|
||||
*aIsApp = (GetFrameType() == eFrameTypeApp);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsContentBoundary(bool* aIsContentBoundary)
|
||||
{
|
||||
switch (GetFrameType()) {
|
||||
case eFrameTypeRegular:
|
||||
*aIsContentBoundary = false;
|
||||
break;
|
||||
case eFrameTypeBrowser:
|
||||
case eFrameTypeApp:
|
||||
*aIsContentBoundary = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsInBrowserElement(bool* aIsInBrowserElement)
|
||||
{
|
||||
@ -12397,50 +12381,29 @@ nsDocShell::GetIsInBrowserElement(bool* aIsInBrowserElement)
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsInApp(bool* aIsInApp)
|
||||
{
|
||||
*aIsInApp = (GetInheritedFrameType() == eFrameTypeApp);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetIsBelowContentBoundary(bool* aIsInContentBoundary)
|
||||
nsDocShell::GetIsInBrowserOrApp(bool* aIsInBrowserOrApp)
|
||||
{
|
||||
switch (GetInheritedFrameType()) {
|
||||
case eFrameTypeRegular:
|
||||
*aIsInContentBoundary = false;
|
||||
*aIsInBrowserOrApp = false;
|
||||
break;
|
||||
case eFrameTypeBrowser:
|
||||
case eFrameTypeApp:
|
||||
*aIsInContentBoundary = true;
|
||||
*aIsInBrowserOrApp = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetAppId(uint32_t aAppId)
|
||||
{
|
||||
MOZ_ASSERT(mAppId == nsIScriptSecurityManager::NO_APP_ID);
|
||||
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
|
||||
|
||||
mAppId = aAppId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [infallible] */ NS_IMETHODIMP
|
||||
nsDocShell::GetAppId(uint32_t* aAppId)
|
||||
{
|
||||
if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
MOZ_ASSERT(GetFrameType() == eFrameTypeApp);
|
||||
|
||||
*aAppId = mAppId;
|
||||
if (mOwnOrContainingAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||
*aAppId = mOwnOrContainingAppId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(GetFrameType() != eFrameTypeApp);
|
||||
|
||||
nsCOMPtr<nsIDocShell> parent;
|
||||
GetSameTypeParentIgnoreBrowserAndAppBoundaries(getter_AddRefs(parent));
|
||||
|
||||
|
@ -665,13 +665,12 @@ protected:
|
||||
bool JustStartedNetworkLoad();
|
||||
|
||||
enum FrameType {
|
||||
eFrameTypeRegular = 0x0, // 0000
|
||||
eFrameTypeBrowser = 0x1, // 0001
|
||||
eFrameTypeApp = 0x2 // 0010
|
||||
eFrameTypeRegular,
|
||||
eFrameTypeBrowser,
|
||||
eFrameTypeApp
|
||||
};
|
||||
|
||||
FrameType GetInheritedFrameType();
|
||||
FrameType GetFrameType();
|
||||
|
||||
// hash of session storages, keyed by domain
|
||||
nsInterfaceHashtable<nsCStringHashKey, nsIDOMStorage> mStorages;
|
||||
@ -808,7 +807,6 @@ protected:
|
||||
bool mIsAppTab;
|
||||
bool mUseGlobalHistory;
|
||||
bool mInPrivateBrowsing;
|
||||
bool mIsBrowserFrame;
|
||||
|
||||
// This boolean is set to true right before we fire pagehide and generally
|
||||
// unset when we embed a new content viewer. While it's true no navigation
|
||||
@ -845,7 +843,18 @@ protected:
|
||||
|
||||
nsRefPtr<nsDOMNavigationTiming> mTiming;
|
||||
|
||||
uint32_t mAppId;
|
||||
// Are we a regular frame, a browser frame, or an app frame?
|
||||
FrameType mFrameType;
|
||||
|
||||
// We only expect mOwnOrContainingAppId to be something other than
|
||||
// UNKNOWN_APP_ID if mFrameType != eFrameTypeRegular. For vanilla iframes
|
||||
// inside an app, we'll retrieve the containing app-id by walking up the
|
||||
// docshell hierarchy.
|
||||
//
|
||||
// (This needs to be the docshell's own /or containing/ app id because the
|
||||
// containing app frame might be in another process, in which case we won't
|
||||
// find it by walking up the docshell hierarchy.)
|
||||
uint32_t mOwnOrContainingAppId;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIAtom> mForcedCharset;
|
||||
|
@ -39,7 +39,7 @@ interface nsIWebBrowserPrint;
|
||||
interface nsIVariant;
|
||||
interface nsIPrivacyTransitionObserver;
|
||||
|
||||
[scriptable, builtinclass, uuid(0132C0BE-ACB5-4D61-9B19-01C005E030DA)]
|
||||
[scriptable, builtinclass, uuid(318CE516-3F7A-41F6-8F3D-3661650F7A46)]
|
||||
interface nsIDocShell : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -579,72 +579,88 @@ interface nsIDocShell : nsISupports
|
||||
void addWeakPrivacyTransitionObserver(in nsIPrivacyTransitionObserver obs);
|
||||
|
||||
/**
|
||||
* Mark the docshell as a browser frame.
|
||||
* This should be used for <iframe mozbrowser> but not for <iframe mozapp>.
|
||||
*
|
||||
* This method should not be called more than once.
|
||||
*/
|
||||
void setIsBrowserElement();
|
||||
|
||||
/**
|
||||
* Returns true iff the docshell is marked as a browser frame.
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser>.
|
||||
* (<iframe mozapp mozbrowser> is not considered a browser.)
|
||||
*/
|
||||
[infallible] readonly attribute boolean isBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns true iif the docshell is marked as an app frame.
|
||||
* Returns true iff the docshell corresponds to an <iframe mozapp>.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isApp;
|
||||
|
||||
/**
|
||||
* Returns true iif the docshell is marked as a type that behaves like a
|
||||
* content boundary.
|
||||
* Returns isBrowserElement || isApp.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isContentBoundary;
|
||||
[infallible] readonly attribute boolean isBrowserOrApp;
|
||||
|
||||
/**
|
||||
* Returns true iif the docshell is inside a browser element.
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser> or if
|
||||
* the docshell is contained in an <iframe mozbrowser>. (<iframe mozapp
|
||||
* mozbrowser> does not count as a browser.)
|
||||
*
|
||||
* Our notion here of "contained in" means: Walk up the docshell hierarchy in
|
||||
* this process until we hit an <iframe mozapp> or <iframe mozbrowser> (or
|
||||
* until the hierarchy ends). Return true iff the docshell we stopped on has
|
||||
* isBrowserElement == true.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isInBrowserElement;
|
||||
|
||||
/**
|
||||
* Returns true iif the docshell is inside an application. However, it will
|
||||
* return false if the docshell is inside a browser element that is inside
|
||||
* an application.
|
||||
* Returns true if this docshell corresponds to an <iframe mozbrowser> or
|
||||
* <iframe mozap>, or if this docshell is contained in an <iframe mozbrowser>
|
||||
* or <iframe mozapp>.
|
||||
*
|
||||
* Note: Do not use this method for permissions checks! An app may contain
|
||||
* an <iframe> pointing at arbitrary web code. This iframe's docshell will
|
||||
* have isInApp() == true, but the iframe's content is not "app code", and
|
||||
* so should not be granted more trust than vanilla web content.
|
||||
*
|
||||
* (For example, suppose when web content calls API method X, we show a
|
||||
* permission prompt, but when "app code" calls method X, we don't. In this
|
||||
* case, it would be /incorrect/ to show the permission prompt if
|
||||
* !isInApp().)
|
||||
*
|
||||
* If you're doing a security check, use the content's principal instead of
|
||||
* this method.
|
||||
* To compute this value, we walk up the docshell hierarchy. If we encounter
|
||||
* a docshell with isBrowserElement or isApp before we hit the end of the
|
||||
* hierarchy, we return true. Otherwise, we return false.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isInApp;
|
||||
[infallible] readonly attribute boolean isInBrowserOrApp;
|
||||
|
||||
/**
|
||||
* Indicate that this docshell corresponds to an app with the given app id.
|
||||
*
|
||||
* You may pass NO_APP_ID or UNKNOWN_APP_ID for containingAppId. If you
|
||||
* pass NO_APP_ID, then this docshell will return NO_APP_ID for appId. If
|
||||
* you pass UNKNOWN_APP_ID, then this docshell will search its hiearchy for
|
||||
* an app frame and use that frame's appId.
|
||||
*
|
||||
* You can call this method more than once, but there's no guarantee that
|
||||
* other components will update their view of the world if you change a
|
||||
* docshell's app id, so tread lightly.
|
||||
*
|
||||
* If you call this method after calling setIsBrowserInsideApp, this
|
||||
* docshell will forget the fact that it was a browser.
|
||||
*/
|
||||
void setIsApp(in unsigned long ownAppId);
|
||||
|
||||
/**
|
||||
* Indicate that this docshell corresponds to a browser inside an app with
|
||||
* the given ID. As with setIsApp, you may pass NO_APP_ID or
|
||||
* UNKNOWN_APP_ID.
|
||||
*
|
||||
* As with setIsApp, you may call this more than once, but it's kind of a
|
||||
* hack, so be careful.
|
||||
*/
|
||||
void setIsBrowserInsideApp(in unsigned long containingAppId);
|
||||
|
||||
/**
|
||||
* Returns if the docshell has a docshell that behaves as a content boundary
|
||||
* in his parent hierarchy.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isBelowContentBoundary;
|
||||
|
||||
/**
|
||||
* Set the app id this docshell is associated with. The id has to be a valid
|
||||
* app id. If the docshell isn't associated with any app, the value should be
|
||||
* nsIScriptSecurityManager::NO_APP_ID. However, this is the default value if
|
||||
* nothing is et.
|
||||
* Returns the id of the app associated with this docshell. If this docshell
|
||||
* is an <iframe mozbrowser> inside an <iframe mozapp>, we return the app's
|
||||
* appId.
|
||||
*
|
||||
* This method is [noscript] to reduce the scope. It should be used at very
|
||||
* specific moments.
|
||||
* We compute this value by walking up the docshell hierarchy until we find a
|
||||
* docshell on which setIsApp(x) or setIsBrowserInsideApp(x) was called
|
||||
* (ignoring those docshells where x == UNKNOWN_APP_ID). We return the app
|
||||
* id x.
|
||||
*
|
||||
* Calling setAppId() will mark the frame as an app frame.
|
||||
* If we don't find a docshell with an associated app id in our hierarchy, we
|
||||
* return NO_APP_ID. We never return UNKNOWN_APP_ID.
|
||||
*
|
||||
* Notice that a docshell may have an associated app even if it returns true
|
||||
* for isBrowserElement!
|
||||
*/
|
||||
[noscript] void setAppId(in unsigned long appId);
|
||||
[infallible] readonly attribute unsigned long appId;
|
||||
|
||||
/**
|
||||
* Like nsIDocShellTreeItem::GetSameTypeParent, except this ignores <iframe
|
||||
|
@ -2924,7 +2924,7 @@ nsGlobalWindow::GetScriptableParent(nsIDOMWindow** aParent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mDocShell->GetIsContentBoundary()) {
|
||||
if (mDocShell->GetIsBrowserOrApp()) {
|
||||
nsCOMPtr<nsIDOMWindow> parent = static_cast<nsIDOMWindow*>(this);
|
||||
parent.swap(*aParent);
|
||||
return NS_OK;
|
||||
@ -3029,9 +3029,9 @@ nsGlobalWindow::GetContent(nsIDOMWindow** aContent)
|
||||
FORWARD_TO_OUTER(GetContent, (aContent), NS_ERROR_NOT_INITIALIZED);
|
||||
*aContent = nullptr;
|
||||
|
||||
// If we're contained in <iframe mozbrowser>, then GetContent is the same as
|
||||
// window.top.
|
||||
if (mDocShell && mDocShell->GetIsBelowContentBoundary()) {
|
||||
// If we're contained in <iframe mozbrowser> or <iframe mozapp>, then
|
||||
// GetContent is the same as window.top.
|
||||
if (mDocShell && mDocShell->GetIsInBrowserOrApp()) {
|
||||
return GetScriptableTop(aContent);
|
||||
}
|
||||
|
||||
@ -6488,7 +6488,7 @@ nsGlobalWindow::Close()
|
||||
FORWARD_TO_OUTER(Close, (), NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (!mDocShell || IsInModalState() ||
|
||||
(IsFrame() && !mDocShell->GetIsContentBoundary())) {
|
||||
(IsFrame() && !mDocShell->GetIsBrowserOrApp())) {
|
||||
// window.close() is called on a frame in a frameset, on a window
|
||||
// that's already closed, or on a window for which there's
|
||||
// currently a modal dialog open. Ignore such calls.
|
||||
@ -7007,8 +7007,9 @@ nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
|
||||
* nsIGlobalWindow::frameElement.
|
||||
*
|
||||
* In contrast to GetRealFrameElement, GetScriptableFrameElement says that the
|
||||
* window contained by an <iframe mozbrowser> has no frame element
|
||||
* (effectively treating a mozbrowser the same as a content/chrome boundary).
|
||||
* window contained by an <iframe mozbrowser> or <iframe mozapp> has no frame
|
||||
* element (effectively treating a mozbrowser the same as a content/chrome
|
||||
* boundary).
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::GetScriptableFrameElement(nsIDOMElement** aFrameElement)
|
||||
@ -7016,7 +7017,7 @@ nsGlobalWindow::GetScriptableFrameElement(nsIDOMElement** aFrameElement)
|
||||
FORWARD_TO_OUTER(GetScriptableFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
|
||||
*aFrameElement = NULL;
|
||||
|
||||
if (!mDocShell || mDocShell->GetIsContentBoundary()) {
|
||||
if (!mDocShell || mDocShell->GetIsBrowserOrApp()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
interface nsITabParent;
|
||||
|
||||
[scriptable, uuid(6f043e42-02c9-4e8f-8f8d-1b83c6102827)]
|
||||
[scriptable, builtinclass, uuid(929AED00-3E15-49B7-8CA2-75003715B7E7)]
|
||||
interface nsIMozBrowserFrame : nsIDOMMozBrowserFrame
|
||||
{
|
||||
/**
|
||||
@ -19,7 +19,7 @@ interface nsIMozBrowserFrame : nsIDOMMozBrowserFrame
|
||||
* nsIDOMMozBrowserFrame::mozbrowser attribute must be true, and the frame
|
||||
* may have to pass various security checks.
|
||||
*/
|
||||
readonly attribute boolean reallyIsBrowser;
|
||||
[infallible] readonly attribute boolean reallyIsBrowserOrApp;
|
||||
|
||||
/**
|
||||
* Gets whether this frame really is an app frame.
|
||||
@ -28,11 +28,13 @@ interface nsIMozBrowserFrame : nsIDOMMozBrowserFrame
|
||||
* frame (this requirement will go away eventually), and the frame's mozapp
|
||||
* attribute must point to the manifest of a valid app.
|
||||
*/
|
||||
readonly attribute boolean reallyIsApp;
|
||||
[infallible] readonly attribute boolean reallyIsApp;
|
||||
|
||||
/**
|
||||
* Gets this frame's app manifest URL, if the frame really is an app frame.
|
||||
* Otherwise, returns the empty string.
|
||||
*
|
||||
* This method is guaranteed not to fail.
|
||||
*/
|
||||
readonly attribute AString appManifestURL;
|
||||
|
||||
|
@ -27,7 +27,7 @@ AssertAppProcessPermission(PBrowserParent* aActor, const char* aPermission)
|
||||
}
|
||||
|
||||
TabParent* tab = static_cast<TabParent*>(aActor);
|
||||
nsCOMPtr<mozIApplication> app = tab->GetApp();
|
||||
nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
|
||||
bool hasPermission = false;
|
||||
|
||||
// isBrowser frames inherit their app descriptor to identify their
|
||||
|
@ -231,13 +231,11 @@ ConsoleListener::Observe(nsIConsoleMessage* aMessage)
|
||||
ContentChild* ContentChild::sSingleton;
|
||||
|
||||
ContentChild::ContentChild()
|
||||
:
|
||||
mID(uint64_t(-1))
|
||||
: TabContext()
|
||||
, mID(uint64_t(-1))
|
||||
#ifdef ANDROID
|
||||
,mScreenSize(0, 0)
|
||||
#endif
|
||||
, mIsForApp(false)
|
||||
, mIsForBrowser(false)
|
||||
{
|
||||
// This process is a content process, so it's clearly running in
|
||||
// multiprocess mode!
|
||||
@ -301,7 +299,7 @@ ContentChild::Init(MessageLoop* aIOLoop,
|
||||
startBackground ? hal::PROCESS_PRIORITY_BACKGROUND:
|
||||
hal::PROCESS_PRIORITY_FOREGROUND);
|
||||
if (mIsForApp && !mIsForBrowser) {
|
||||
SetProcessName(NS_LITERAL_STRING("(App)"));
|
||||
SetProcessName(NS_LITERAL_STRING("(Preallocated app)"));
|
||||
} else {
|
||||
SetProcessName(NS_LITERAL_STRING("Browser"));
|
||||
}
|
||||
@ -489,8 +487,8 @@ static void FirstIdle(void)
|
||||
}
|
||||
|
||||
PBrowserChild*
|
||||
ContentChild::AllocPBrowser(const uint32_t& aChromeFlags,
|
||||
const bool& aIsBrowserElement, const AppId& aApp)
|
||||
ContentChild::AllocPBrowser(const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags)
|
||||
{
|
||||
static bool firstIdleTaskPosted = false;
|
||||
if (!firstIdleTaskPosted) {
|
||||
@ -498,8 +496,12 @@ ContentChild::AllocPBrowser(const uint32_t& aChromeFlags,
|
||||
firstIdleTaskPosted = true;
|
||||
}
|
||||
|
||||
nsRefPtr<TabChild> child =
|
||||
TabChild::Create(aChromeFlags, aIsBrowserElement, aApp.get_uint32_t());
|
||||
// We'll happily accept any kind of IPCTabContext here; we don't need to
|
||||
// check that it's of a certain type for security purposes, because we
|
||||
// believe whatever the parent process tells us.
|
||||
|
||||
nsRefPtr<TabChild> child = TabChild::Create(TabContext(aContext), aChromeFlags);
|
||||
|
||||
// The ref here is released below.
|
||||
return child.forget().get();
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/PContentChild.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
@ -40,6 +41,7 @@ class PStorageChild;
|
||||
class ClonedMessageData;
|
||||
|
||||
class ContentChild : public PContentChild
|
||||
, public TabContext
|
||||
{
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
|
||||
@ -78,9 +80,8 @@ public:
|
||||
AllocPImageBridge(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBrowserChild* AllocPBrowser(const uint32_t& aChromeFlags,
|
||||
const bool& aIsBrowserElement,
|
||||
const AppId& aAppId);
|
||||
virtual PBrowserChild* AllocPBrowser(const IPCTabContext &aContext,
|
||||
const uint32_t &chromeFlags);
|
||||
virtual bool DeallocPBrowser(PBrowserChild*);
|
||||
|
||||
virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequest(const DeviceStorageParams&);
|
||||
@ -195,9 +196,6 @@ public:
|
||||
|
||||
uint64_t GetID() { return mID; }
|
||||
|
||||
bool IsForApp() { return mIsForApp; }
|
||||
bool IsForBrowser() { return mIsForBrowser; }
|
||||
|
||||
BlobChild* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
|
||||
|
||||
private:
|
||||
|
@ -55,7 +55,6 @@
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIAlertsService.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsIClipboard.h"
|
||||
#include "nsIDOMApplicationRegistry.h"
|
||||
#include "nsIDOMGeoGeolocation.h"
|
||||
@ -317,27 +316,25 @@ AppNeedsInheritedOSPrivileges(mozIApplication* aApp)
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement)
|
||||
ContentParent::CreateBrowserOrApp(const TabContext& aContext)
|
||||
{
|
||||
// We currently don't set the <app> ancestor for <browser> content
|
||||
// correctly. This assertion is to notify the person who fixes
|
||||
// this code that they need to reevaluate places here where we may
|
||||
// make bad assumptions based on that bug.
|
||||
MOZ_ASSERT(!aApp || !aIsBrowserElement);
|
||||
|
||||
if (!aApp) {
|
||||
if (ContentParent* cp = GetNewOrUsed(aIsBrowserElement)) {
|
||||
nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement));
|
||||
return static_cast<TabParent*>(
|
||||
cp->SendPBrowserConstructor(
|
||||
// DeallocPBrowserParent() releases the ref we take here
|
||||
tp.forget().get(),
|
||||
/*chromeFlags*/0,
|
||||
aIsBrowserElement, nsIScriptSecurityManager::NO_APP_ID));
|
||||
if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
|
||||
if (ContentParent* cp = GetNewOrUsed(aContext.IsBrowserElement())) {
|
||||
nsRefPtr<TabParent> tp(new TabParent(aContext));
|
||||
PBrowserParent* browser = cp->SendPBrowserConstructor(
|
||||
tp.forget().get(), // DeallocPBrowserParent() releases this ref.
|
||||
aContext.AsIPCTabContext(),
|
||||
/* chromeFlags */ 0);
|
||||
return static_cast<TabParent*>(browser);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If we got here, we have an app and we're not a browser element. ownApp
|
||||
// shouldn't be null, because we otherwise would have gone into the
|
||||
// !HasOwnApp() branch above.
|
||||
nsCOMPtr<mozIApplication> ownApp = aContext.GetOwnApp();
|
||||
|
||||
if (!gAppContentParents) {
|
||||
gAppContentParents =
|
||||
new nsDataHashtable<nsStringHashKey, ContentParent*>();
|
||||
@ -346,29 +343,15 @@ ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement)
|
||||
|
||||
// Each app gets its own ContentParent instance.
|
||||
nsAutoString manifestURL;
|
||||
if (NS_FAILED(aApp->GetManifestURL(manifestURL))) {
|
||||
if (NS_FAILED(ownApp->GetManifestURL(manifestURL))) {
|
||||
NS_ERROR("Failed to get manifest URL");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
if (!appsService) {
|
||||
NS_ERROR("Failed to get apps service");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Send the local app ID to the new TabChild so it knows what app
|
||||
// it is.
|
||||
uint32_t appId;
|
||||
if (NS_FAILED(appsService->GetAppLocalIdByManifestURL(manifestURL, &appId))) {
|
||||
NS_ERROR("Failed to get local app ID");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<ContentParent> p = gAppContentParents->Get(manifestURL);
|
||||
if (!p) {
|
||||
if (AppNeedsInheritedOSPrivileges(aApp)) {
|
||||
p = new ContentParent(manifestURL, aIsBrowserElement,
|
||||
if (AppNeedsInheritedOSPrivileges(ownApp)) {
|
||||
p = new ContentParent(manifestURL, /* isBrowserElement = */ false,
|
||||
base::PRIVILEGES_INHERIT);
|
||||
p->Init();
|
||||
} else {
|
||||
@ -377,7 +360,7 @@ ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement)
|
||||
p->SetManifestFromPreallocated(manifestURL);
|
||||
} else {
|
||||
NS_WARNING("Unable to use pre-allocated app process");
|
||||
p = new ContentParent(manifestURL, aIsBrowserElement,
|
||||
p = new ContentParent(manifestURL, /* isBrowserElement = */ false,
|
||||
base::PRIVILEGES_DEFAULT);
|
||||
p->Init();
|
||||
}
|
||||
@ -385,12 +368,12 @@ ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement)
|
||||
gAppContentParents->Put(manifestURL, p);
|
||||
}
|
||||
|
||||
nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement));
|
||||
return static_cast<TabParent*>(
|
||||
// DeallocPBrowserParent() releases the ref we take here
|
||||
p->SendPBrowserConstructor(tp.forget().get(),
|
||||
/*chromeFlags*/0,
|
||||
aIsBrowserElement, appId));
|
||||
nsRefPtr<TabParent> tp = new TabParent(aContext);
|
||||
PBrowserParent* browser = p->SendPBrowserConstructor(
|
||||
tp.forget().get(), // DeallocPBrowserParent() releases this ref.
|
||||
aContext.AsIPCTabContext(),
|
||||
/* chromeFlags */ 0);
|
||||
return static_cast<TabParent*>(browser);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
@ -1163,30 +1146,37 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline)
|
||||
}
|
||||
|
||||
PBrowserParent*
|
||||
ContentParent::AllocPBrowser(const uint32_t& aChromeFlags,
|
||||
const bool& aIsBrowserElement, const AppId& aApp)
|
||||
ContentParent::AllocPBrowser(const IPCTabContext& aContext,
|
||||
const uint32_t &aChromeFlags)
|
||||
{
|
||||
// We only use this Alloc() method when the content processes asks
|
||||
// us to open a window. In that case, we're expecting to see the
|
||||
// opening PBrowser as its app descriptor, and we can trust the data
|
||||
// associated with that PBrowser since it's fully owned by this
|
||||
// process.
|
||||
if (AppId::TPBrowserParent != aApp.type()) {
|
||||
NS_ERROR("Content process attempting to forge app ID");
|
||||
return nullptr;
|
||||
}
|
||||
TabParent* opener = static_cast<TabParent*>(aApp.get_PBrowserParent());
|
||||
unused << aChromeFlags;
|
||||
|
||||
// Popup windows of isBrowser frames are isBrowser if the parent
|
||||
// isBrowser. Allocating a !isBrowser frame with same app ID
|
||||
// would allow the content to access data it's not supposed to.
|
||||
if (opener && opener->IsBrowserElement() && !aIsBrowserElement) {
|
||||
NS_ERROR("Content process attempting to escalate data access privileges");
|
||||
// We don't trust the IPCTabContext we receive from the child, so we'll bail
|
||||
// if we receive an IPCTabContext that's not a PopupIPCTabContext.
|
||||
// (PopupIPCTabContext lets the child process prove that it has access to
|
||||
// the app it's trying to open.)
|
||||
if (aContext.type() != IPCTabContext::TPopupIPCTabContext) {
|
||||
NS_ERROR("Unexpected IPCTabContext type. Aborting AllocPBrowser.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TabParent* parent = new TabParent(opener ? opener->GetApp() : nullptr,
|
||||
aIsBrowserElement);
|
||||
const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext();
|
||||
TabParent* opener = static_cast<TabParent*>(popupContext.openerParent());
|
||||
if (!opener) {
|
||||
NS_ERROR("Got null opener from child; aborting AllocPBrowser.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Popup windows of isBrowser frames must be isBrowser if the parent
|
||||
// isBrowser. Allocating a !isBrowser frame with same app ID would allow
|
||||
// the content to access data it's not supposed to.
|
||||
if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) {
|
||||
NS_ERROR("Child trying to escalate privileges! Aborting AllocPBrowser.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TabParent* parent = new TabParent(TabContext(aContext));
|
||||
|
||||
// We release this ref in DeallocPBrowser()
|
||||
NS_ADDREF(parent);
|
||||
return parent;
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "mozilla/dom/PContentParent.h"
|
||||
#include "mozilla/dom/PMemoryReportRequestParent.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/dom/ipc/Blob.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
@ -74,15 +75,9 @@ public:
|
||||
static ContentParent* GetNewOrUsed(bool aForBrowserElement = false);
|
||||
|
||||
/**
|
||||
* Get or create a content process for the given app descriptor,
|
||||
* which may be null. This function will assign processes to app
|
||||
* or non-app browsers by internal heuristics.
|
||||
*
|
||||
* Currently apps are given their own process, and browser tabs
|
||||
* share processes.
|
||||
* Get or create a content process for the given TabContext.
|
||||
*/
|
||||
static TabParent* CreateBrowser(mozIApplication* aApp,
|
||||
bool aIsBrowserFrame);
|
||||
static TabParent* CreateBrowserOrApp(const TabContext& aContext);
|
||||
|
||||
static void GetAll(nsTArray<ContentParent*>& aArray);
|
||||
|
||||
@ -189,9 +184,8 @@ private:
|
||||
bool* aIsForBrowser) MOZ_OVERRIDE;
|
||||
virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBrowserParent* AllocPBrowser(const uint32_t& aChromeFlags,
|
||||
const bool& aIsBrowserElement,
|
||||
const AppId& aApp);
|
||||
virtual PBrowserParent* AllocPBrowser(const IPCTabContext& aContext,
|
||||
const uint32_t& aChromeFlags);
|
||||
virtual bool DeallocPBrowser(PBrowserParent* frame);
|
||||
|
||||
virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequest(const DeviceStorageParams&);
|
||||
|
@ -42,6 +42,7 @@ EXPORTS_mozilla/dom = \
|
||||
StructuredCloneUtils.h \
|
||||
TabParent.h \
|
||||
TabChild.h \
|
||||
TabContext.h \
|
||||
TabMessageUtils.h \
|
||||
$(NULL)
|
||||
|
||||
@ -64,6 +65,7 @@ CPPSRCS = \
|
||||
StructuredCloneUtils.cpp \
|
||||
TabParent.cpp \
|
||||
TabChild.cpp \
|
||||
TabContext.cpp \
|
||||
TabMessageUtils.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
@ -135,9 +135,60 @@ union BlobConstructorParams
|
||||
MysteryBlobConstructorParams;
|
||||
};
|
||||
|
||||
union AppId {
|
||||
uint32_t;
|
||||
nullable PBrowser;
|
||||
// An IPCTabContext which corresponds to a PBrowser opened by a child when it
|
||||
// receives window.open().
|
||||
//
|
||||
// If isBrowserElement is false, this PopupIPCTabContext corresponds to an app
|
||||
// frame, and the frame's app-id and app-frame-owner-app-id will be equal to the
|
||||
// opener's values.
|
||||
//
|
||||
// If isBrowserElement is true, the frame's browserFrameOwnerAppId will be equal
|
||||
// to the opener's app-id.
|
||||
//
|
||||
// It's an error to set isBrowserElement == false if opener is a browser
|
||||
// element. Such a PopupIPCTabContext should be rejected by code which receives
|
||||
// it.
|
||||
struct PopupIPCTabContext
|
||||
{
|
||||
PBrowser opener;
|
||||
bool isBrowserElement;
|
||||
};
|
||||
|
||||
// An IPCTabContext which corresponds to an app frame.
|
||||
struct AppFrameIPCTabContext
|
||||
{
|
||||
// The ID of the app this frame corresponds to. May be NO_APP_ID.
|
||||
uint32_t ownAppId;
|
||||
|
||||
// The ID of the app containing this frame. May be NO_APP_ID.
|
||||
uint32_t appFrameOwnerAppId;
|
||||
};
|
||||
|
||||
// An IPCTabContext which corresponds to a browser frame.
|
||||
struct BrowserFrameIPCTabContext
|
||||
{
|
||||
// The ID of the app which contains this browser frame. May be NO_APP_ID.
|
||||
uint32_t browserFrameOwnerAppId;
|
||||
};
|
||||
|
||||
// This is equivalent to AppFrameIPCTabContext with all fields set to NO_APP_ID.
|
||||
struct VanillaFrameIPCTabContext
|
||||
{};
|
||||
|
||||
// IPCTabContext is an analog to mozilla::dom::TabContext. Both specify an
|
||||
// iframe/PBrowser's own and containing app-ids and tell you whether the
|
||||
// iframe/PBrowser is a browser frame. But only IPCTabContext is allowed to
|
||||
// travel over IPC.
|
||||
//
|
||||
// We need IPCTabContext (specifically, PopupIPCTabContext) to prevent a
|
||||
// privilege escalation attack by a compromised child process. See the comment
|
||||
// on AllocPBrowser for details.
|
||||
union IPCTabContext
|
||||
{
|
||||
PopupIPCTabContext;
|
||||
AppFrameIPCTabContext;
|
||||
BrowserFrameIPCTabContext;
|
||||
VanillaFrameIPCTabContext;
|
||||
};
|
||||
|
||||
union PrefValue {
|
||||
@ -182,16 +233,26 @@ both:
|
||||
// created from either the child or parent process!
|
||||
//
|
||||
// The child creates the PBrowser as part of
|
||||
// TabChild::BrowserFrameProvideWindow, and the parent creates the
|
||||
// PBrowser as part of ContentParent::CreateTab.
|
||||
// TabChild::BrowserFrameProvideWindow (which happens when the child's
|
||||
// content calls window.open()), and the parent creates the PBrowser as part
|
||||
// of ContentParent::CreateTab.
|
||||
//
|
||||
// When the parent constructs a PBrowser, the app ID handed to the
|
||||
// child side is trusted. In that case, |appId| is uint32_t.
|
||||
// However, when the child side constructs a PBrowser, for
|
||||
// window.open(), the parent must validate the app ID used on the
|
||||
// parent side. To do so, the child process must pass a valid
|
||||
// PBrowser as its |AppId|.
|
||||
async PBrowser(uint32_t chromeFlags, bool isBrowserElement, AppId appId);
|
||||
// When the parent constructs a PBrowser, the child trusts the app token it
|
||||
// receives from the parent. In that case, context can be any of the
|
||||
// IPCTabContext subtypes.
|
||||
//
|
||||
// When the child constructs a PBrowser, the parent doesn't trust the app
|
||||
// token it receives from the child. In this case, context must have type
|
||||
// PopupIPCTabContext. The browser created using a PopupIPCTabContext has
|
||||
// the opener PBrowser's app-id and containing-app-id. The parent checks
|
||||
// that if the opener is a browser element, the context is also for a
|
||||
// browser element.
|
||||
//
|
||||
// This allows the parent to prevent a malicious child from escalating its
|
||||
// privileges by requesting a PBrowser corresponding to a highly-privileged
|
||||
// app; the child can only request privileges for an app which the child has
|
||||
// access to (in the form of a TabChild).
|
||||
async PBrowser(IPCTabContext context, uint32_t chromeFlags);
|
||||
|
||||
async PBlob(BlobConstructorParams params);
|
||||
|
||||
|
@ -120,8 +120,7 @@ TabChild::PreloadSlowThings()
|
||||
{
|
||||
MOZ_ASSERT(!sPreallocatedTab);
|
||||
|
||||
nsRefPtr<TabChild> tab(new TabChild(0, false,
|
||||
nsIScriptSecurityManager::NO_APP_ID));
|
||||
nsRefPtr<TabChild> tab(new TabChild(TabContext(), /* chromeFlags */ 0));
|
||||
if (!NS_SUCCEEDED(tab->Init()) ||
|
||||
!tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
|
||||
return;
|
||||
@ -133,41 +132,37 @@ TabChild::PreloadSlowThings()
|
||||
}
|
||||
|
||||
/*static*/ already_AddRefed<TabChild>
|
||||
TabChild::Create(uint32_t aChromeFlags,
|
||||
bool aIsBrowserElement, uint32_t aAppId)
|
||||
TabChild::Create(const TabContext &aContext, uint32_t aChromeFlags)
|
||||
{
|
||||
if (sPreallocatedTab &&
|
||||
sPreallocatedTab->mChromeFlags == aChromeFlags &&
|
||||
(aIsBrowserElement ||
|
||||
aAppId != nsIScriptSecurityManager::NO_APP_ID)) {
|
||||
aContext.IsBrowserOrApp()) {
|
||||
|
||||
nsRefPtr<TabChild> child = sPreallocatedTab.get();
|
||||
sPreallocatedTab = nullptr;
|
||||
|
||||
MOZ_ASSERT(!child->mTriedBrowserInit);
|
||||
|
||||
child->SetAppBrowserConfig(aIsBrowserElement, aAppId);
|
||||
|
||||
child->SetTabContext(aContext);
|
||||
child->NotifyTabContextUpdated();
|
||||
return child.forget();
|
||||
}
|
||||
|
||||
nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement,
|
||||
aAppId);
|
||||
nsRefPtr<TabChild> iframe = new TabChild(aContext, aChromeFlags);
|
||||
return NS_SUCCEEDED(iframe->Init()) ? iframe.forget() : nullptr;
|
||||
}
|
||||
|
||||
|
||||
TabChild::TabChild(uint32_t aChromeFlags, bool aIsBrowserElement,
|
||||
uint32_t aAppId)
|
||||
: mRemoteFrame(nullptr)
|
||||
TabChild::TabChild(const TabContext& aContext, uint32_t aChromeFlags)
|
||||
: TabContext(aContext)
|
||||
, mRemoteFrame(nullptr)
|
||||
, mTabChildGlobal(nullptr)
|
||||
, mChromeFlags(aChromeFlags)
|
||||
, mOuterRect(0, 0, 0, 0)
|
||||
, mInnerSize(0, 0)
|
||||
, mOldViewportWidth(0.0f)
|
||||
, mLastBackgroundColor(NS_RGB(255, 255, 255))
|
||||
, mAppId(aAppId)
|
||||
, mDidFakeShow(false)
|
||||
, mIsBrowserElement(aIsBrowserElement)
|
||||
, mNotified(false)
|
||||
, mContentDocumentIsDisplayed(false)
|
||||
, mTriedBrowserInit(false)
|
||||
@ -530,7 +525,7 @@ TabChild::Init()
|
||||
baseWindow->InitWindow(0, mWidget, 0, 0, 0, 0);
|
||||
baseWindow->Create();
|
||||
|
||||
SetAppBrowserConfig(mIsBrowserElement, mAppId);
|
||||
NotifyTabContextUpdated();
|
||||
|
||||
// IPC uses a WebBrowser object for which DNS prefetching is turned off
|
||||
// by default. But here we really want it, so enable it explicitly
|
||||
@ -554,18 +549,18 @@ TabChild::Init()
|
||||
}
|
||||
|
||||
void
|
||||
TabChild::SetAppBrowserConfig(bool aIsBrowserElement, uint32_t aAppId)
|
||||
TabChild::NotifyTabContextUpdated()
|
||||
{
|
||||
mIsBrowserElement = aIsBrowserElement;
|
||||
mAppId = aAppId;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mWebNav);
|
||||
MOZ_ASSERT(docShell);
|
||||
|
||||
if (docShell) {
|
||||
docShell->SetAppId(mAppId);
|
||||
if (mIsBrowserElement) {
|
||||
docShell->SetIsBrowserElement();
|
||||
// nsDocShell will do the right thing if we pass NO_APP_ID or
|
||||
// UNKNOWN_APP_ID for aOwnOrContainingAppId.
|
||||
if (IsBrowserElement()) {
|
||||
docShell->SetIsBrowserInsideApp(BrowserOwnerAppId());
|
||||
} else {
|
||||
docShell->SetIsApp(OwnAppId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -789,11 +784,11 @@ TabChild::ProvideWindow(nsIDOMWindow* aParent, uint32_t aChromeFlags,
|
||||
{
|
||||
*aReturn = nullptr;
|
||||
|
||||
// If aParent is inside an <iframe mozbrowser> and this isn't a request to
|
||||
// open a modal-type window, we're going to create a new <iframe mozbrowser>
|
||||
// and return its window here.
|
||||
// If aParent is inside an <iframe mozbrowser> or <iframe mozapp> and this
|
||||
// isn't a request to open a modal-type window, we're going to create a new
|
||||
// <iframe mozbrowser/mozapp> and return its window here.
|
||||
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
|
||||
if (docshell && docshell->GetIsBelowContentBoundary() &&
|
||||
if (docshell && docshell->GetIsInBrowserOrApp() &&
|
||||
!(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
|
||||
@ -828,16 +823,25 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
||||
{
|
||||
*aReturn = nullptr;
|
||||
|
||||
uint32_t chromeFlags = 0;
|
||||
nsRefPtr<TabChild> newChild = new TabChild(chromeFlags,
|
||||
mIsBrowserElement, mAppId);
|
||||
nsRefPtr<TabChild> newChild =
|
||||
new TabChild(/* TabContext */ *this, /* chromeFlags */ 0);
|
||||
if (!NS_SUCCEEDED(newChild->Init())) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
// We must use PopupIPCTabContext here; ContentParent will not accept the
|
||||
// result of this->AsIPCTabContext() (which will be a
|
||||
// BrowserFrameIPCTabContext or an AppFrameIPCTabContext), for security
|
||||
// reasons.
|
||||
PopupIPCTabContext context;
|
||||
context.openerChild() = this;
|
||||
context.isBrowserElement() = IsBrowserElement();
|
||||
|
||||
unused << Manager()->SendPBrowserConstructor(
|
||||
// We release this ref in DeallocPBrowserChild
|
||||
nsRefPtr<TabChild>(newChild).forget().get(),
|
||||
chromeFlags, mIsBrowserElement, this);
|
||||
context, /* chromeFlags */ 0);
|
||||
|
||||
nsAutoCString spec;
|
||||
if (aURI) {
|
||||
aURI->GetSpec(spec);
|
||||
@ -998,29 +1002,13 @@ TabChild::~TabChild()
|
||||
void
|
||||
TabChild::SetProcessNameToAppName()
|
||||
{
|
||||
if (mIsBrowserElement || (mAppId == nsIScriptSecurityManager::NO_APP_ID)) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIAppsService> appsService =
|
||||
do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
if (!appsService) {
|
||||
NS_WARNING("No AppsService");
|
||||
return;
|
||||
}
|
||||
nsresult rv;
|
||||
nsCOMPtr<mozIDOMApplication> domApp;
|
||||
rv = appsService->GetAppByLocalId(mAppId, getter_AddRefs(domApp));
|
||||
if (NS_FAILED(rv) || !domApp) {
|
||||
NS_WARNING("GetAppByLocalId failed");
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
|
||||
nsCOMPtr<mozIApplication> app = GetOwnApp();
|
||||
if (!app) {
|
||||
NS_WARNING("app isn't a mozIApplication");
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString appName;
|
||||
rv = app->GetName(appName);
|
||||
nsresult rv = app->GetName(appName);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to retrieve app name");
|
||||
return;
|
||||
@ -1032,19 +1020,25 @@ TabChild::SetProcessNameToAppName()
|
||||
bool
|
||||
TabChild::IsRootContentDocument()
|
||||
{
|
||||
if (mIsBrowserElement || mAppId == nsIScriptSecurityManager::NO_APP_ID) {
|
||||
// We're the child side of a browser element. This always
|
||||
// behaves like a root content document.
|
||||
return true;
|
||||
}
|
||||
// A TabChild is a "root content document" if it's
|
||||
//
|
||||
// - <iframe mozapp> not inside another <iframe mozapp>,
|
||||
// - <iframe mozbrowser> (not mozapp), or
|
||||
// - a vanilla remote frame (<html:iframe remote=true> or <xul:browser
|
||||
// remote=true>).
|
||||
//
|
||||
// Put another way, an iframe is /not/ a "root content document" iff it's a
|
||||
// mozapp inside a mozapp. (This corresponds exactly to !HasAppOwnerApp.)
|
||||
//
|
||||
// Note that we're lying through our teeth here (thus the scare quotes).
|
||||
// <html:iframe remote=true> or <xul:browser remote=true> inside another
|
||||
// content iframe is not actually a root content document, but we say it is.
|
||||
//
|
||||
// We do this because we make a remote frame opaque iff
|
||||
// IsRootContentDocument(), and making vanilla remote frames transparent
|
||||
// breaks our remote reftests.
|
||||
|
||||
// Otherwise, we're the child side of an <html:app remote=true>
|
||||
// embedded in an outer <html:app>. These don't behave like root
|
||||
// content documents in nested contexts. Because of bug 761935,
|
||||
// <html:browser remote> and <html:app remote> can't nest, so we
|
||||
// assume this isn't the root. When that bug is fixed, we need to
|
||||
// revisit that assumption.
|
||||
return false;
|
||||
return !HasAppOwnerApp();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1702,7 +1696,7 @@ TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
|
||||
mTriedBrowserInit = true;
|
||||
// Initialize the child side of the browser element machinery,
|
||||
// if appropriate.
|
||||
if (mIsBrowserElement || mAppId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
if (IsBrowserOrApp()) {
|
||||
RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT);
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "ProcessUtils.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
|
||||
struct gfxMatrix;
|
||||
|
||||
@ -149,7 +150,8 @@ class TabChild : public PBrowserChild,
|
||||
public nsIDialogCreator,
|
||||
public nsITabChild,
|
||||
public nsIObserver,
|
||||
public mozilla::dom::ipc::MessageManagerCallback
|
||||
public ipc::MessageManagerCallback,
|
||||
public TabContext
|
||||
{
|
||||
typedef mozilla::layout::RenderFrameChild RenderFrameChild;
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
@ -164,12 +166,10 @@ public:
|
||||
|
||||
/** Return a TabChild with the given attributes. */
|
||||
static already_AddRefed<TabChild>
|
||||
Create(uint32_t aChromeFlags, bool aIsBrowserElement, uint32_t aAppId);
|
||||
Create(const TabContext& aContext, uint32_t aChromeFlags);
|
||||
|
||||
virtual ~TabChild();
|
||||
|
||||
uint32_t GetAppId() { return mAppId; }
|
||||
|
||||
bool IsRootContentDocument();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -320,15 +320,21 @@ private:
|
||||
/**
|
||||
* Create a new TabChild object.
|
||||
*
|
||||
* |aIsBrowserElement| indicates whether the tab is inside an <iframe mozbrowser>.
|
||||
* |aAppId| is the app id of the app containing this tab. If the tab isn't
|
||||
* contained in an app, aAppId will be nsIScriptSecurityManager::NO_APP_ID.
|
||||
* |aOwnOrContainingAppId| is the app-id of our frame or of the closest app
|
||||
* frame in the hierarchy which contains us.
|
||||
*
|
||||
* |aIsBrowserElement| indicates whether we're a browser (but not an app).
|
||||
*/
|
||||
TabChild(uint32_t aChromeFlags, bool aIsBrowserElement, uint32_t aAppId);
|
||||
TabChild(const TabContext& aContext, uint32_t aChromeFlags);
|
||||
|
||||
nsresult Init();
|
||||
|
||||
void SetAppBrowserConfig(bool aIsBrowserElement, uint32_t aAppId);
|
||||
// Notify others that our TabContext has been updated. (At the moment, this
|
||||
// sets the appropriate app-id and is-browser flags on our docshell.)
|
||||
//
|
||||
// You should call this after calling TabContext::SetTabContext(). We also
|
||||
// call this during Init().
|
||||
void NotifyTabContextUpdated();
|
||||
|
||||
bool UseDirectCompositor();
|
||||
|
||||
@ -392,9 +398,7 @@ private:
|
||||
float mOldViewportWidth;
|
||||
nscolor mLastBackgroundColor;
|
||||
ScrollingBehavior mScrolling;
|
||||
uint32_t mAppId;
|
||||
bool mDidFakeShow;
|
||||
bool mIsBrowserElement;
|
||||
bool mNotified;
|
||||
bool mContentDocumentIsDisplayed;
|
||||
bool mTriedBrowserInit;
|
||||
|
292
dom/ipc/TabContext.cpp
Normal file
292
dom/ipc/TabContext.cpp
Normal file
@ -0,0 +1,292 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "nsIAppsService.h"
|
||||
|
||||
using namespace mozilla::dom::ipc;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
TabContext::TabContext()
|
||||
: mInitialized(false)
|
||||
, mOwnAppId(nsIScriptSecurityManager::NO_APP_ID)
|
||||
, mContainingAppId(nsIScriptSecurityManager::NO_APP_ID)
|
||||
, mIsBrowser(false)
|
||||
{
|
||||
}
|
||||
|
||||
TabContext::TabContext(const IPCTabContext& aParams)
|
||||
: mInitialized(true)
|
||||
{
|
||||
switch(aParams.type()) {
|
||||
case IPCTabContext::TPopupIPCTabContext: {
|
||||
const PopupIPCTabContext &ipcContext = aParams.get_PopupIPCTabContext();
|
||||
|
||||
TabContext *context;
|
||||
if (ipcContext.openerParent()) {
|
||||
context = static_cast<TabParent*>(ipcContext.openerParent());
|
||||
if (context->IsBrowserElement() && !ipcContext.isBrowserElement()) {
|
||||
// If the TabParent corresponds to a browser element, then it can only
|
||||
// open other browser elements, for security reasons. We should have
|
||||
// checked this before calling the TabContext constructor, so this is
|
||||
// a fatal error.
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
else if (ipcContext.openerChild()) {
|
||||
context = static_cast<TabChild*>(ipcContext.openerChild());
|
||||
}
|
||||
else {
|
||||
// This should be unreachable because PopupIPCTabContext::opener is not a
|
||||
// nullable field.
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// If ipcContext is a browser element, then the opener's app-id becomes
|
||||
// our containing app-id. Otherwise, our own and containing app-ids are
|
||||
// directly inherited from our opener.
|
||||
if (ipcContext.isBrowserElement()) {
|
||||
mIsBrowser = true;
|
||||
mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
mContainingAppId = context->OwnAppId();
|
||||
}
|
||||
else {
|
||||
mIsBrowser = false;
|
||||
mOwnAppId = context->mOwnAppId;
|
||||
mContainingAppId = context->mContainingAppId;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCTabContext::TAppFrameIPCTabContext: {
|
||||
const AppFrameIPCTabContext &ipcContext =
|
||||
aParams.get_AppFrameIPCTabContext();
|
||||
|
||||
mIsBrowser = false;
|
||||
mOwnAppId = ipcContext.ownAppId();
|
||||
mContainingAppId = ipcContext.appFrameOwnerAppId();
|
||||
break;
|
||||
}
|
||||
case IPCTabContext::TBrowserFrameIPCTabContext: {
|
||||
const BrowserFrameIPCTabContext &ipcContext =
|
||||
aParams.get_BrowserFrameIPCTabContext();
|
||||
|
||||
mIsBrowser = true;
|
||||
mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
mContainingAppId = ipcContext.browserFrameOwnerAppId();
|
||||
break;
|
||||
}
|
||||
case IPCTabContext::TVanillaFrameIPCTabContext: {
|
||||
mIsBrowser = false;
|
||||
mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
mContainingAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::IsBrowserElement() const
|
||||
{
|
||||
return mIsBrowser;
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::IsBrowserOrApp() const
|
||||
{
|
||||
return HasOwnApp() || IsBrowserElement();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TabContext::OwnAppId() const
|
||||
{
|
||||
return mOwnAppId;
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetOwnApp() const
|
||||
{
|
||||
return GetAppForId(OwnAppId());
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::HasOwnApp() const
|
||||
{
|
||||
return mOwnAppId != nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TabContext::BrowserOwnerAppId() const
|
||||
{
|
||||
if (mIsBrowser) {
|
||||
return mContainingAppId;
|
||||
}
|
||||
return nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetBrowserOwnerApp() const
|
||||
{
|
||||
return GetAppForId(BrowserOwnerAppId());
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::HasBrowserOwnerApp() const
|
||||
{
|
||||
return BrowserOwnerAppId() != nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TabContext::AppOwnerAppId() const
|
||||
{
|
||||
if (mOwnAppId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
return mContainingAppId;
|
||||
}
|
||||
return nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetAppOwnerApp() const
|
||||
{
|
||||
return GetAppForId(AppOwnerAppId());
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::HasAppOwnerApp() const
|
||||
{
|
||||
return AppOwnerAppId() != nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TabContext::OwnOrContainingAppId() const
|
||||
{
|
||||
if (mIsBrowser) {
|
||||
MOZ_ASSERT(mOwnAppId == nsIScriptSecurityManager::NO_APP_ID);
|
||||
return mContainingAppId;
|
||||
}
|
||||
|
||||
if (mOwnAppId) {
|
||||
return mOwnAppId;
|
||||
}
|
||||
|
||||
return mContainingAppId;
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetOwnOrContainingApp() const
|
||||
{
|
||||
return GetAppForId(OwnOrContainingAppId());
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::HasOwnOrContainingApp() const
|
||||
{
|
||||
return OwnOrContainingAppId() != nsIScriptSecurityManager::NO_APP_ID;
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::SetTabContext(const TabContext& aContext)
|
||||
{
|
||||
NS_ENSURE_FALSE(mInitialized, false);
|
||||
|
||||
// Verify that we can actually get apps for the given ids. This step gives us
|
||||
// confidence that HasX() returns true iff GetX() returns true.
|
||||
if (aContext.mOwnAppId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
nsCOMPtr<mozIApplication> app = GetAppForId(aContext.mOwnAppId);
|
||||
NS_ENSURE_TRUE(app, false);
|
||||
}
|
||||
|
||||
if (aContext.mContainingAppId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
nsCOMPtr<mozIApplication> app = GetAppForId(aContext.mContainingAppId);
|
||||
NS_ENSURE_TRUE(app, false);
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
mIsBrowser = aContext.mIsBrowser;
|
||||
mOwnAppId = aContext.mOwnAppId;
|
||||
mContainingAppId = aContext.mContainingAppId;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp, mozIApplication* aAppFrameOwnerApp)
|
||||
{
|
||||
NS_ENSURE_FALSE(mInitialized, false);
|
||||
|
||||
// Get ids for both apps and only write to our member variables after we've
|
||||
// verified that this worked.
|
||||
uint32_t ownAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (aOwnApp) {
|
||||
nsresult rv = aOwnApp->GetLocalId(&ownAppId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
|
||||
uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (aAppFrameOwnerApp) {
|
||||
nsresult rv = aOwnApp->GetLocalId(&containingAppId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
mIsBrowser = false;
|
||||
mOwnAppId = ownAppId;
|
||||
mContainingAppId = containingAppId;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp)
|
||||
{
|
||||
NS_ENSURE_FALSE(mInitialized, false);
|
||||
|
||||
uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
if (aBrowserFrameOwnerApp) {
|
||||
nsresult rv = aBrowserFrameOwnerApp->GetLocalId(&containingAppId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
mIsBrowser = true;
|
||||
mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
mContainingAppId = containingAppId;
|
||||
return true;
|
||||
}
|
||||
|
||||
IPCTabContext
|
||||
TabContext::AsIPCTabContext() const
|
||||
{
|
||||
if (mIsBrowser) {
|
||||
return BrowserFrameIPCTabContext(mContainingAppId);
|
||||
}
|
||||
|
||||
return AppFrameIPCTabContext(mOwnAppId, mContainingAppId);
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetAppForId(uint32_t aAppId) const
|
||||
{
|
||||
if (aAppId == nsIScriptSecurityManager::NO_APP_ID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(appsService, nullptr);
|
||||
|
||||
nsCOMPtr<mozIDOMApplication> domApp;
|
||||
appsService->GetAppByLocalId(aAppId, getter_AddRefs(domApp));
|
||||
|
||||
nsCOMPtr<mozIApplication> app = do_QueryInterface(domApp);
|
||||
return app.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
209
dom/ipc/TabContext.h
Normal file
209
dom/ipc/TabContext.h
Normal file
@ -0,0 +1,209 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_TabContext_h
|
||||
#define mozilla_dom_TabContext_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/PContent.h"
|
||||
#include "mozilla/dom/PBrowser.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "mozIApplication.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* TabContext encapsulates information about an iframe that may be a mozbrowser
|
||||
* or mozapp. You can ask whether a TabContext correspodns to a mozbrowser or
|
||||
* mozapp, get the app that contains the browser, and so on.
|
||||
*
|
||||
* TabParent and TabChild both inherit from TabContext, and you can also have
|
||||
* standalone TabContext objects.
|
||||
*
|
||||
* This class is immutable except by calling one of the protected
|
||||
* SetTabContext*() methods (and those methods can only be called once). See
|
||||
* also MutableTabContext.
|
||||
*/
|
||||
class TabContext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor sets is-browser to false, and sets all relevant apps to
|
||||
* NO_APP_ID. If you inherit from TabContext, you can mutate this object
|
||||
* exactly once by calling one of the protected SetTabContext*() methods.
|
||||
*/
|
||||
TabContext();
|
||||
|
||||
/**
|
||||
* This constructor copies the information in aContext. The TabContext is
|
||||
* immutable after calling this method; you won't be able call any of the
|
||||
* protected SetTabContext*() methods on an object constructed using this
|
||||
* constructor.
|
||||
*
|
||||
* If aContext is a PopupIPCTabContext with isBrowserElement false and whose
|
||||
* openerParent is a browser element, this constructor will crash (even in
|
||||
* release builds). So please check that case before calling this method.
|
||||
*/
|
||||
TabContext(const IPCTabContext& aContext);
|
||||
|
||||
/**
|
||||
* Generates IPCTabContext of type BrowserFrameIPCTabContext or
|
||||
* AppFrameIPCTabContext from this TabContext's information.
|
||||
*/
|
||||
IPCTabContext AsIPCTabContext() const;
|
||||
|
||||
/**
|
||||
* Does this TabContext correspond to a mozbrowser? (<iframe mozbrowser
|
||||
* mozapp> is not a browser.)
|
||||
*
|
||||
* If IsBrowserElement() is true, HasOwnApp() and HasAppOwnerApp() are
|
||||
* guaranteed to be false.
|
||||
*
|
||||
* If IsBrowserElement() is false, HasBrowserOwnerApp() is guaranteed to be
|
||||
* false.
|
||||
*/
|
||||
bool IsBrowserElement() const;
|
||||
|
||||
/**
|
||||
* Does this TabContext correspond to a mozbrowser or mozapp? This is
|
||||
* equivalent to IsBrowserElement() || HasOwnApp().
|
||||
*/
|
||||
bool IsBrowserOrApp() const;
|
||||
|
||||
/**
|
||||
* OwnAppId() returns the id of the app which directly corresponds to this
|
||||
* context's frame. GetOwnApp() returns the corresponding app object, and
|
||||
* HasOwnApp() returns true iff GetOwnApp() would return a non-null value.
|
||||
*
|
||||
* If HasOwnApp() is true, IsBrowserElement() is guaranteed to be false.
|
||||
*/
|
||||
uint32_t OwnAppId() const;
|
||||
already_AddRefed<mozIApplication> GetOwnApp() const;
|
||||
bool HasOwnApp() const;
|
||||
|
||||
/**
|
||||
* BrowserOwnerAppId() gets the ID of the app which contains this browser
|
||||
* frame. If this is not a browser frame (i.e., if !IsBrowserElement()), then
|
||||
* BrowserOwnerAppId() is guaranteed to return NO_APP_ID.
|
||||
*
|
||||
* Even if we are a browser frame, BrowserOwnerAppId() may still return
|
||||
* NO_APP_ID, if this browser frame is not contained inside an app.
|
||||
*/
|
||||
uint32_t BrowserOwnerAppId() const;
|
||||
already_AddRefed<mozIApplication> GetBrowserOwnerApp() const;
|
||||
bool HasBrowserOwnerApp() const;
|
||||
|
||||
/**
|
||||
* AppOwnerAppId() gets the ID of the app which contains this app frame. If
|
||||
* this is not an app frame (i.e., if !HasOwnApp()), then AppOwnerAppId() is
|
||||
* guaranteed to return NO_APP_ID.
|
||||
*
|
||||
* Even if we are an app frame, AppOwnerAppId() may still return NO_APP_ID, if
|
||||
* this app frame is not contained inside an app.
|
||||
*/
|
||||
uint32_t AppOwnerAppId() const;
|
||||
already_AddRefed<mozIApplication> GetAppOwnerApp() const;
|
||||
bool HasAppOwnerApp() const;
|
||||
|
||||
/**
|
||||
* OwnOrContainingAppId() gets the ID of this frame, if HasOwnApp(). If this
|
||||
* frame does not have its own app, it gets the ID of the app which contains
|
||||
* this frame (i.e., the result of {Browser,App}OwnerAppId(), as applicable).
|
||||
*/
|
||||
uint32_t OwnOrContainingAppId() const;
|
||||
already_AddRefed<mozIApplication> GetOwnOrContainingApp() const;
|
||||
bool HasOwnOrContainingApp() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* These protected mutator methods let you modify a TabContext once. Further
|
||||
* attempts to modify a given TabContext will fail (the method will return
|
||||
* false).
|
||||
*
|
||||
* These mutators will also fail if the TabContext was created with anything
|
||||
* other than the no-args constructor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set this TabContext to match the given TabContext.
|
||||
*/
|
||||
bool SetTabContext(const TabContext& aContext);
|
||||
|
||||
/**
|
||||
* Set this TabContext to be an app frame (with the given own app) inside the
|
||||
* given app. Either or both apps may be null.
|
||||
*/
|
||||
bool SetTabContextForAppFrame(mozIApplication* aOwnApp,
|
||||
mozIApplication* aAppFrameOwnerApp);
|
||||
|
||||
/**
|
||||
* Set this TabContext to be a browser frame inside the given app (which may
|
||||
* be null).
|
||||
*/
|
||||
bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Translate an appId into a mozIApplication.
|
||||
*/
|
||||
already_AddRefed<mozIApplication> GetAppForId(uint32_t aAppId) const;
|
||||
|
||||
/**
|
||||
* Has this TabContext been initialized? If so, mutator methods will fail.
|
||||
*/
|
||||
bool mInitialized;
|
||||
|
||||
/**
|
||||
* This TabContext's own app id. If this is something other than NO_APP_ID,
|
||||
* then this TabContext corresponds to an app, and mIsBrowser must be false.
|
||||
*/
|
||||
uint32_t mOwnAppId;
|
||||
|
||||
/**
|
||||
* The id of the app which contains this TabContext's frame. If mIsBrowser,
|
||||
* this corresponds to the ID of the app which contains the browser frame;
|
||||
* otherwise, this correspodns to the ID of the app which contains the app
|
||||
* frame.
|
||||
*/
|
||||
uint32_t mContainingAppId;
|
||||
|
||||
/**
|
||||
* Does this TabContext correspond to a browser element?
|
||||
*
|
||||
* If this is true, mOwnAppId must be NO_APP_ID.
|
||||
*/
|
||||
bool mIsBrowser;
|
||||
};
|
||||
|
||||
/**
|
||||
* MutableTabContext is the same as TabContext, except the mutation methods are
|
||||
* public instead of protected. You can still only call these mutation methods
|
||||
* once on a given object.
|
||||
*/
|
||||
class MutableTabContext : public TabContext
|
||||
{
|
||||
public:
|
||||
bool SetTabContext(const TabContext& aContext)
|
||||
{
|
||||
return TabContext::SetTabContext(aContext);
|
||||
}
|
||||
|
||||
bool SetTabContextForAppFrame(mozIApplication* aOwnApp, mozIApplication* aAppFrameOwnerApp)
|
||||
{
|
||||
return TabContext::SetTabContextForAppFrame(aOwnApp, aAppFrameOwnerApp);
|
||||
}
|
||||
|
||||
bool SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp)
|
||||
{
|
||||
return TabContext::SetTabContextForBrowserFrame(aBrowserFrameOwnerApp);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -73,9 +73,9 @@ TabParent *TabParent::mIMETabParent = nullptr;
|
||||
|
||||
NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
|
||||
|
||||
TabParent::TabParent(mozIApplication* aApp, bool aIsBrowserElement)
|
||||
: mFrameElement(NULL)
|
||||
, mApp(aApp)
|
||||
TabParent::TabParent(const TabContext& aContext)
|
||||
: TabContext(aContext)
|
||||
, mFrameElement(NULL)
|
||||
, mIMESelectionAnchor(0)
|
||||
, mIMESelectionFocus(0)
|
||||
, mIMEComposing(false)
|
||||
@ -85,7 +85,6 @@ TabParent::TabParent(mozIApplication* aApp, bool aIsBrowserElement)
|
||||
, mEventCaptureDepth(0)
|
||||
, mDimensions(0, 0)
|
||||
, mDPI(0)
|
||||
, mIsBrowserElement(aIsBrowserElement)
|
||||
, mShown(false)
|
||||
{
|
||||
}
|
||||
@ -188,7 +187,7 @@ TabParent::AnswerCreateWindow(PBrowserParent** retval)
|
||||
}
|
||||
|
||||
// Only non-app, non-browser processes may call CreateWindow.
|
||||
if (GetApp() || IsBrowserElement()) {
|
||||
if (IsBrowserOrApp()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -897,9 +896,9 @@ TabParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
|
||||
// XXXbent Need to make sure we have a whitelist for chrome databases!
|
||||
|
||||
// Verify the appID in the origin first.
|
||||
if (mApp && !aASCIIOrigin.EqualsLiteral("chrome")) {
|
||||
if (mOwnOrContainingApp && !aASCIIOrigin.EqualsLiteral("chrome")) {
|
||||
uint32_t appId;
|
||||
rv = mApp->GetLocalId(&appId);
|
||||
rv = mOwnOrContainingApp->GetLocalId(&appId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
if (!IndexedDatabaseManager::OriginMatchesApp(aASCIIOrigin, appId)) {
|
||||
@ -1163,29 +1162,14 @@ TabParent::GetWidget() const
|
||||
return widget.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::IsForMozBrowser()
|
||||
{
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(content);
|
||||
if (browserFrame) {
|
||||
bool isBrowser = false;
|
||||
browserFrame->GetReallyIsBrowser(&isBrowser);
|
||||
return isBrowser;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::UseAsyncPanZoom()
|
||||
{
|
||||
bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
|
||||
bool asyncPanZoomEnabled =
|
||||
Preferences::GetBool("layers.async-pan-zoom.enabled", false);
|
||||
ContentParent* cp = static_cast<ContentParent*>(Manager());
|
||||
return (usingOffMainThreadCompositing &&
|
||||
!cp->IsForApp() && IsForMozBrowser() &&
|
||||
asyncPanZoomEnabled);
|
||||
IsBrowserElement() && asyncPanZoomEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/dom/PBrowserParent.h"
|
||||
#include "mozilla/dom/PContentDialogParent.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
@ -50,11 +51,12 @@ class TabParent : public PBrowserParent
|
||||
, public nsITabParent
|
||||
, public nsIAuthPromptProvider
|
||||
, public nsISecureBrowserUI
|
||||
, public TabContext
|
||||
{
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
|
||||
public:
|
||||
TabParent(mozIApplication* aApp, bool aIsBrowserElement);
|
||||
TabParent(const TabContext& aContext);
|
||||
virtual ~TabParent();
|
||||
nsIDOMElement* GetOwnerElement() { return mFrameElement; }
|
||||
void SetOwnerElement(nsIDOMElement* aElement);
|
||||
@ -62,9 +64,6 @@ public:
|
||||
void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
|
||||
mBrowserDOMWindow = aBrowserDOMWindow;
|
||||
}
|
||||
|
||||
mozIApplication* GetApp() { return mApp; }
|
||||
bool IsBrowserElement() { return mIsBrowserElement; }
|
||||
|
||||
/**
|
||||
* Return the TabParent that has decided it wants to capture an
|
||||
@ -262,7 +261,6 @@ protected:
|
||||
uint64_t* aLayersId) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPRenderFrame(PRenderFrameParent* aFrame) MOZ_OVERRIDE;
|
||||
|
||||
nsCOMPtr<mozIApplication> mApp;
|
||||
// IME
|
||||
static TabParent *mIMETabParent;
|
||||
nsString mIMECacheText;
|
||||
@ -281,7 +279,6 @@ protected:
|
||||
|
||||
nsIntSize mDimensions;
|
||||
float mDPI;
|
||||
bool mIsBrowserElement;
|
||||
bool mShown;
|
||||
|
||||
private:
|
||||
@ -289,9 +286,7 @@ private:
|
||||
already_AddRefed<nsIWidget> GetWidget() const;
|
||||
layout::RenderFrameParent* GetRenderFrame();
|
||||
void TryCacheDPI();
|
||||
// Return true iff this TabParent was created for a mozbrowser
|
||||
// frame.
|
||||
bool IsForMozBrowser();
|
||||
|
||||
// When true, we create a pan/zoom controller for our frame and
|
||||
// notify it of input events targeting us.
|
||||
bool UseAsyncPanZoom();
|
||||
|
@ -1633,12 +1633,8 @@ uint32_t nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow *aParent,
|
||||
// Disable CHROME_OPENAS_DIALOG if the window is inside <iframe mozbrowser>.
|
||||
// It's up to the embedder to interpret what dialog=1 means.
|
||||
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
|
||||
if (docshell) {
|
||||
bool belowContentBoundary = false;
|
||||
docshell->GetIsBelowContentBoundary(&belowContentBoundary);
|
||||
if (belowContentBoundary) {
|
||||
chromeFlags &= ~nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
|
||||
}
|
||||
if (docshell && docshell->GetIsInBrowserOrApp()) {
|
||||
chromeFlags &= ~nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
|
||||
}
|
||||
|
||||
return chromeFlags;
|
||||
|
@ -196,9 +196,8 @@ gfxAndroidPlatform::FontHintingEnabled()
|
||||
#else
|
||||
// Otherwise, enable hinting unless we're in a content process
|
||||
// that might be used for non-reflowing zoom.
|
||||
return (XRE_GetProcessType() != GeckoProcessType_Content ||
|
||||
(ContentChild::GetSingleton()->IsForApp() &&
|
||||
!ContentChild::GetSingleton()->IsForBrowser()));
|
||||
return XRE_GetProcessType() != GeckoProcessType_Content ||
|
||||
ContentChild::GetSingleton()->HasOwnApp();
|
||||
#endif // MOZ_USING_ANDROID_JAVA_WIDGETS
|
||||
}
|
||||
|
||||
|
@ -851,7 +851,7 @@ nsContentTreeOwner::ProvideWindow(nsIDOMWindow* aParent,
|
||||
// open a modal-type window, we're going to create a new <iframe mozbrowser>
|
||||
// and return its window here.
|
||||
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
|
||||
if (docshell && docshell->GetIsBelowContentBoundary() &&
|
||||
if (docshell && docshell->GetIsInBrowserOrApp() &&
|
||||
!(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
|
||||
|
Loading…
Reference in New Issue
Block a user