mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 896890 - TabContent::HasOwnApp() should be true iff TabContext::GetOwnApp() is non-null. r=khuey
This change reworks how TabContext stores its data. Before, it stored an app-id and translated that into an app; now we do the reverse. This lets us guarantee that HasOwnApp() is true iff GetOwnApp() is non-null. We added a new class, MaybeInvalidTabContext to assist with converting from an IPCTabContext to a TabContext. This allows us to ensure that a TabContext object is never invalid. --HG-- extra : rebase_source : d43e858739a342ab420122a90336bfd585be268a
This commit is contained in:
parent
6c2e8f4922
commit
7aa4dc5297
@ -2056,12 +2056,15 @@ nsFrameLoader::TryRemoteBrowser()
|
||||
eCaseMatters)) {
|
||||
scrollingBehavior = ASYNC_PAN_ZOOM;
|
||||
}
|
||||
|
||||
bool rv = true;
|
||||
if (ownApp) {
|
||||
context.SetTabContextForAppFrame(ownApp, containingApp, scrollingBehavior);
|
||||
rv = context.SetTabContextForAppFrame(ownApp, containingApp, scrollingBehavior);
|
||||
} else if (OwnerIsBrowserFrame()) {
|
||||
// The |else| above is unnecessary; OwnerIsBrowserFrame() implies !ownApp.
|
||||
context.SetTabContextForBrowserFrame(containingApp, scrollingBehavior);
|
||||
rv = context.SetTabContextForBrowserFrame(containingApp, scrollingBehavior);
|
||||
}
|
||||
NS_ENSURE_TRUE(rv, false);
|
||||
|
||||
nsCOMPtr<Element> ownerElement = mOwnerContent;
|
||||
mRemoteBrowser = ContentParent::CreateBrowserOrApp(context, ownerElement);
|
||||
|
@ -591,7 +591,15 @@ ContentChild::AllocPBrowserChild(const IPCTabContext& aContext,
|
||||
// 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(this, TabContext(aContext), aChromeFlags);
|
||||
MaybeInvalidTabContext tc(aContext);
|
||||
if (!tc.IsValid()) {
|
||||
NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
|
||||
"the parent process. (%s) Crashing...",
|
||||
tc.InvalidReason()));
|
||||
MOZ_CRASH("Invalid TabContext received from the parent process.");
|
||||
}
|
||||
|
||||
nsRefPtr<TabChild> child = TabChild::Create(this, tc.GetTabContext(), aChromeFlags);
|
||||
|
||||
// The ref here is released in DeallocPBrowserChild.
|
||||
return child.forget().get();
|
||||
|
@ -1757,7 +1757,15 @@ ContentParent::AllocPBrowserParent(const IPCTabContext& aContext,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TabParent* parent = new TabParent(this, TabContext(aContext));
|
||||
MaybeInvalidTabContext tc(aContext);
|
||||
if (!tc.IsValid()) {
|
||||
NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) "
|
||||
"Aborting AllocPBrowserParent.",
|
||||
tc.InvalidReason()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TabParent* parent = new TabParent(this, tc.GetTabContext());
|
||||
|
||||
// We release this ref in DeallocPBrowserParent()
|
||||
NS_ADDREF(parent);
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "nsIAppsService.h"
|
||||
|
||||
#define NO_APP_ID (nsIScriptSecurityManager::NO_APP_ID)
|
||||
|
||||
using namespace mozilla::dom::ipc;
|
||||
using namespace mozilla::layout;
|
||||
|
||||
@ -17,92 +19,13 @@ namespace dom {
|
||||
|
||||
TabContext::TabContext()
|
||||
: mInitialized(false)
|
||||
, mOwnAppId(nsIScriptSecurityManager::NO_APP_ID)
|
||||
, mContainingAppId(nsIScriptSecurityManager::NO_APP_ID)
|
||||
, mOwnAppId(NO_APP_ID)
|
||||
, mContainingAppId(NO_APP_ID)
|
||||
, mScrollingBehavior(DEFAULT_SCROLLING)
|
||||
, mIsBrowser(false)
|
||||
{
|
||||
}
|
||||
|
||||
TabContext::TabContext(const IPCTabContext& aParams)
|
||||
: mInitialized(true)
|
||||
{
|
||||
const IPCTabAppBrowserContext& appBrowser = aParams.appBrowserContext();
|
||||
switch(appBrowser.type()) {
|
||||
case IPCTabAppBrowserContext::TPopupIPCTabContext: {
|
||||
const PopupIPCTabContext &ipcContext = appBrowser.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();
|
||||
}
|
||||
|
||||
// Browser elements can't nest other browser elements. So if
|
||||
// our opener is browser element, we must be a new DOM window
|
||||
// opened by it. In that case we inherit our containing app ID
|
||||
// (if any).
|
||||
//
|
||||
// Otherwise, we're a new app window and we inherit from our
|
||||
// opener app.
|
||||
if (ipcContext.isBrowserElement()) {
|
||||
mIsBrowser = true;
|
||||
mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
mContainingAppId = context->OwnOrContainingAppId();
|
||||
}
|
||||
else {
|
||||
mIsBrowser = false;
|
||||
mOwnAppId = context->mOwnAppId;
|
||||
mContainingAppId = context->mContainingAppId;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCTabAppBrowserContext::TAppFrameIPCTabContext: {
|
||||
const AppFrameIPCTabContext &ipcContext =
|
||||
appBrowser.get_AppFrameIPCTabContext();
|
||||
|
||||
mIsBrowser = false;
|
||||
mOwnAppId = ipcContext.ownAppId();
|
||||
mContainingAppId = ipcContext.appFrameOwnerAppId();
|
||||
break;
|
||||
}
|
||||
case IPCTabAppBrowserContext::TBrowserFrameIPCTabContext: {
|
||||
const BrowserFrameIPCTabContext &ipcContext =
|
||||
appBrowser.get_BrowserFrameIPCTabContext();
|
||||
|
||||
mIsBrowser = true;
|
||||
mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
mContainingAppId = ipcContext.browserFrameOwnerAppId();
|
||||
break;
|
||||
}
|
||||
case IPCTabAppBrowserContext::TVanillaFrameIPCTabContext: {
|
||||
mIsBrowser = false;
|
||||
mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
mContainingAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
mScrollingBehavior = aParams.scrollingBehavior();
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::IsBrowserElement() const
|
||||
{
|
||||
@ -124,66 +47,73 @@ TabContext::OwnAppId() const
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetOwnApp() const
|
||||
{
|
||||
return GetAppForId(OwnAppId());
|
||||
nsCOMPtr<mozIApplication> ownApp = mOwnApp;
|
||||
return ownApp.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::HasOwnApp() const
|
||||
{
|
||||
return mOwnAppId != nsIScriptSecurityManager::NO_APP_ID;
|
||||
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
|
||||
return !!ownApp;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TabContext::BrowserOwnerAppId() const
|
||||
{
|
||||
if (mIsBrowser) {
|
||||
if (IsBrowserElement()) {
|
||||
return mContainingAppId;
|
||||
}
|
||||
return nsIScriptSecurityManager::NO_APP_ID;
|
||||
return NO_APP_ID;
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetBrowserOwnerApp() const
|
||||
{
|
||||
return GetAppForId(BrowserOwnerAppId());
|
||||
nsCOMPtr<mozIApplication> ownerApp;
|
||||
if (IsBrowserElement()) {
|
||||
ownerApp = mContainingApp;
|
||||
}
|
||||
return ownerApp.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::HasBrowserOwnerApp() const
|
||||
{
|
||||
return BrowserOwnerAppId() != nsIScriptSecurityManager::NO_APP_ID;
|
||||
nsCOMPtr<mozIApplication> ownerApp = GetBrowserOwnerApp();
|
||||
return !!ownerApp;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TabContext::AppOwnerAppId() const
|
||||
{
|
||||
if (mOwnAppId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
if (HasOwnApp()) {
|
||||
return mContainingAppId;
|
||||
}
|
||||
return nsIScriptSecurityManager::NO_APP_ID;
|
||||
return NO_APP_ID;
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetAppOwnerApp() const
|
||||
{
|
||||
return GetAppForId(AppOwnerAppId());
|
||||
nsCOMPtr<mozIApplication> ownerApp;
|
||||
if (HasOwnApp()) {
|
||||
ownerApp = mContainingApp;
|
||||
}
|
||||
return ownerApp.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::HasAppOwnerApp() const
|
||||
{
|
||||
return AppOwnerAppId() != nsIScriptSecurityManager::NO_APP_ID;
|
||||
nsCOMPtr<mozIApplication> ownerApp = GetAppOwnerApp();
|
||||
return !!ownerApp;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TabContext::OwnOrContainingAppId() const
|
||||
{
|
||||
if (mIsBrowser) {
|
||||
MOZ_ASSERT(mOwnAppId == nsIScriptSecurityManager::NO_APP_ID);
|
||||
return mContainingAppId;
|
||||
}
|
||||
|
||||
if (mOwnAppId) {
|
||||
if (HasOwnApp()) {
|
||||
return mOwnAppId;
|
||||
}
|
||||
|
||||
@ -193,13 +123,21 @@ TabContext::OwnOrContainingAppId() const
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetOwnOrContainingApp() const
|
||||
{
|
||||
return GetAppForId(OwnOrContainingAppId());
|
||||
nsCOMPtr<mozIApplication> ownOrContainingApp;
|
||||
if (HasOwnApp()) {
|
||||
ownOrContainingApp = mOwnApp;
|
||||
} else {
|
||||
ownOrContainingApp = mContainingApp;
|
||||
}
|
||||
|
||||
return ownOrContainingApp.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::HasOwnOrContainingApp() const
|
||||
{
|
||||
return OwnOrContainingAppId() != nsIScriptSecurityManager::NO_APP_ID;
|
||||
nsCOMPtr<mozIApplication> ownOrContainingApp = GetOwnOrContainingApp();
|
||||
return !!ownOrContainingApp;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -207,44 +145,33 @@ 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);
|
||||
}
|
||||
|
||||
*this = aContext;
|
||||
mInitialized = true;
|
||||
mIsBrowser = aContext.mIsBrowser;
|
||||
mOwnAppId = aContext.mOwnAppId;
|
||||
mContainingAppId = aContext.mContainingAppId;
|
||||
mScrollingBehavior = aContext.mScrollingBehavior;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp, mozIApplication* aAppFrameOwnerApp,
|
||||
TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp,
|
||||
mozIApplication* aAppFrameOwnerApp,
|
||||
ScrollingBehavior aRequestedBehavior)
|
||||
{
|
||||
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;
|
||||
uint32_t ownAppId = NO_APP_ID;
|
||||
if (aOwnApp) {
|
||||
nsresult rv = aOwnApp->GetLocalId(&ownAppId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
NS_ENSURE_TRUE(ownAppId != NO_APP_ID, false);
|
||||
}
|
||||
|
||||
uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
uint32_t containingAppId = NO_APP_ID;
|
||||
if (aAppFrameOwnerApp) {
|
||||
nsresult rv = aOwnApp->GetLocalId(&containingAppId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
@ -252,6 +179,8 @@ TabContext::SetTabContextForAppFrame(mozIApplication* aOwnApp, mozIApplication*
|
||||
mOwnAppId = ownAppId;
|
||||
mContainingAppId = containingAppId;
|
||||
mScrollingBehavior = aRequestedBehavior;
|
||||
mOwnApp = aOwnApp;
|
||||
mContainingApp = aAppFrameOwnerApp;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -261,17 +190,19 @@ TabContext::SetTabContextForBrowserFrame(mozIApplication* aBrowserFrameOwnerApp,
|
||||
{
|
||||
NS_ENSURE_FALSE(mInitialized, false);
|
||||
|
||||
uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
uint32_t containingAppId = NO_APP_ID;
|
||||
if (aBrowserFrameOwnerApp) {
|
||||
nsresult rv = aBrowserFrameOwnerApp->GetLocalId(&containingAppId);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
mIsBrowser = true;
|
||||
mOwnAppId = nsIScriptSecurityManager::NO_APP_ID;
|
||||
mOwnAppId = NO_APP_ID;
|
||||
mContainingAppId = containingAppId;
|
||||
mScrollingBehavior = aRequestedBehavior;
|
||||
mContainingApp = aBrowserFrameOwnerApp;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -287,38 +218,8 @@ TabContext::AsIPCTabContext() const
|
||||
mScrollingBehavior);
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetAppForId(uint32_t aAppId) const
|
||||
{
|
||||
if (aAppId == nsIScriptSecurityManager::NO_APP_ID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This application caching is needed to avoid numerous unecessary application clones.
|
||||
// See Bug 853632 for details.
|
||||
|
||||
if (aAppId == mOwnAppId) {
|
||||
if (!mOwnApp) {
|
||||
mOwnApp = GetAppForIdNoCache(aAppId);
|
||||
}
|
||||
nsCOMPtr<mozIApplication> ownApp = mOwnApp;
|
||||
return ownApp.forget();
|
||||
}
|
||||
|
||||
if (aAppId == mContainingAppId) {
|
||||
if (!mContainingApp) {
|
||||
mContainingApp = GetAppForIdNoCache(mContainingAppId);
|
||||
}
|
||||
nsCOMPtr<mozIApplication> containingApp = mContainingApp;
|
||||
return containingApp.forget();
|
||||
}
|
||||
// We need the fallthrough here because mOwnAppId/mContainingAppId aren't always
|
||||
// set before calling GetAppForId().
|
||||
return GetAppForIdNoCache(aAppId);
|
||||
}
|
||||
|
||||
already_AddRefed<mozIApplication>
|
||||
TabContext::GetAppForIdNoCache(uint32_t aAppId) const
|
||||
static already_AddRefed<mozIApplication>
|
||||
GetAppForId(uint32_t aAppId)
|
||||
{
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(appsService, nullptr);
|
||||
@ -330,5 +231,136 @@ TabContext::GetAppForIdNoCache(uint32_t aAppId) const
|
||||
return app.forget();
|
||||
}
|
||||
|
||||
MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
|
||||
: mInvalidReason(nullptr)
|
||||
{
|
||||
bool isBrowser = false;
|
||||
uint32_t ownAppId = NO_APP_ID;
|
||||
uint32_t containingAppId = NO_APP_ID;
|
||||
|
||||
const IPCTabAppBrowserContext& appBrowser = aParams.appBrowserContext();
|
||||
switch(appBrowser.type()) {
|
||||
case IPCTabAppBrowserContext::TPopupIPCTabContext: {
|
||||
const PopupIPCTabContext &ipcContext = appBrowser.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.
|
||||
mInvalidReason = "Child is-browser process tried to "
|
||||
"open a non-browser tab.";
|
||||
return;
|
||||
}
|
||||
} else if (ipcContext.openerChild()) {
|
||||
context = static_cast<TabChild*>(ipcContext.openerChild());
|
||||
} else {
|
||||
// This should be unreachable because PopupIPCTabContext::opener is not a
|
||||
// nullable field.
|
||||
mInvalidReason = "PopupIPCTabContext::opener was null (?!).";
|
||||
return;
|
||||
}
|
||||
|
||||
// Browser elements can't nest other browser elements. So if
|
||||
// our opener is browser element, we must be a new DOM window
|
||||
// opened by it. In that case we inherit our containing app ID
|
||||
// (if any).
|
||||
//
|
||||
// Otherwise, we're a new app window and we inherit from our
|
||||
// opener app.
|
||||
if (ipcContext.isBrowserElement()) {
|
||||
isBrowser = true;
|
||||
ownAppId = NO_APP_ID;
|
||||
containingAppId = context->OwnOrContainingAppId();
|
||||
} else {
|
||||
isBrowser = false;
|
||||
ownAppId = context->mOwnAppId;
|
||||
containingAppId = context->mContainingAppId;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCTabAppBrowserContext::TAppFrameIPCTabContext: {
|
||||
const AppFrameIPCTabContext &ipcContext =
|
||||
appBrowser.get_AppFrameIPCTabContext();
|
||||
|
||||
isBrowser = false;
|
||||
ownAppId = ipcContext.ownAppId();
|
||||
containingAppId = ipcContext.appFrameOwnerAppId();
|
||||
break;
|
||||
}
|
||||
case IPCTabAppBrowserContext::TBrowserFrameIPCTabContext: {
|
||||
const BrowserFrameIPCTabContext &ipcContext =
|
||||
appBrowser.get_BrowserFrameIPCTabContext();
|
||||
|
||||
isBrowser = true;
|
||||
ownAppId = NO_APP_ID;
|
||||
containingAppId = ipcContext.browserFrameOwnerAppId();
|
||||
break;
|
||||
}
|
||||
case IPCTabAppBrowserContext::TVanillaFrameIPCTabContext: {
|
||||
isBrowser = false;
|
||||
ownAppId = NO_APP_ID;
|
||||
containingAppId = NO_APP_ID;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIApplication> ownApp = GetAppForId(ownAppId);
|
||||
if (ownApp == nullptr !=
|
||||
ownAppId == NO_APP_ID) {
|
||||
mInvalidReason = "Got an ownAppId that didn't correspond to an app.";
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIApplication> containingApp = GetAppForId(containingAppId);
|
||||
if (containingApp == nullptr !=
|
||||
containingAppId == NO_APP_ID) {
|
||||
mInvalidReason = "Got a containingAppId that didn't correspond to an app.";
|
||||
return;
|
||||
}
|
||||
|
||||
bool rv;
|
||||
if (isBrowser) {
|
||||
rv = mTabContext.SetTabContextForBrowserFrame(containingApp,
|
||||
aParams.scrollingBehavior());
|
||||
} else {
|
||||
rv = mTabContext.SetTabContextForAppFrame(ownApp,
|
||||
containingApp,
|
||||
aParams.scrollingBehavior());
|
||||
}
|
||||
|
||||
if (!rv) {
|
||||
mInvalidReason = "Couldn't initialize TabContext.";
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MaybeInvalidTabContext::IsValid()
|
||||
{
|
||||
return mInvalidReason == nullptr;
|
||||
}
|
||||
|
||||
const char*
|
||||
MaybeInvalidTabContext::GetInvalidReason()
|
||||
{
|
||||
return mInvalidReason;
|
||||
}
|
||||
|
||||
const TabContext&
|
||||
MaybeInvalidTabContext::GetTabContext()
|
||||
{
|
||||
if (!IsValid()) {
|
||||
MOZ_CRASH("Can't GetTabContext() if !IsValid().");
|
||||
}
|
||||
|
||||
return mTabContext;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -35,24 +35,9 @@ protected:
|
||||
typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
|
||||
|
||||
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);
|
||||
/* (The implicit copy-constructor and operator= are fine.) */
|
||||
|
||||
/**
|
||||
* Generates IPCTabContext of type BrowserFrameIPCTabContext or
|
||||
@ -128,6 +113,8 @@ public:
|
||||
ScrollingBehavior GetScrollingBehavior() const { return mScrollingBehavior; }
|
||||
|
||||
protected:
|
||||
friend class MaybeInvalidTabContext;
|
||||
|
||||
/**
|
||||
* These protected mutator methods let you modify a TabContext once. Further
|
||||
* attempts to modify a given TabContext will fail (the method will return
|
||||
@ -158,48 +145,35 @@ protected:
|
||||
ScrollingBehavior aRequestedBehavior);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Translate an appId into a mozIApplication, using lazy caching.
|
||||
*/
|
||||
already_AddRefed<mozIApplication> GetAppForId(uint32_t aAppId) const;
|
||||
|
||||
/**
|
||||
* Translate an appId into a mozIApplication.
|
||||
*/
|
||||
already_AddRefed<mozIApplication> GetAppForIdNoCache(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.
|
||||
* This TabContext's own app. If this is non-null, then this
|
||||
* TabContext corresponds to an app, and mIsBrowser must be false.
|
||||
*/
|
||||
nsCOMPtr<mozIApplication> mOwnApp;
|
||||
|
||||
/**
|
||||
* A cache of mOwnApp->GetLocalId(). Speed really does matter here, since we
|
||||
* read this ID often during process startup.
|
||||
*/
|
||||
uint32_t mOwnAppId;
|
||||
|
||||
/**
|
||||
* Cache of this TabContext's own app. If mOwnAppId is NO_APP_ID, this is
|
||||
* guaranteed to be nullptr. Otherwise, it may or may not be null.
|
||||
* This TabContext's containing app. If mIsBrowser, this corresponds to the
|
||||
* app which contains the browser frame; otherwise, this corresponds to the
|
||||
* app which contains the app frame.
|
||||
*/
|
||||
mutable nsCOMPtr<mozIApplication> mOwnApp;
|
||||
nsCOMPtr<mozIApplication> mContainingApp;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
/*
|
||||
* Cache of mContainingApp->GetLocalId().
|
||||
*/
|
||||
uint32_t mContainingAppId;
|
||||
|
||||
/**
|
||||
* Cache of the app that contains this TabContext's frame. If mContainingAppId
|
||||
* is NO_APP_ID, this is guaranteed to be nullptr. Otherwise, it may or may not
|
||||
* be null.
|
||||
*/
|
||||
mutable nsCOMPtr<mozIApplication> mContainingApp;
|
||||
|
||||
/**
|
||||
* The requested scrolling behavior for this frame.
|
||||
*/
|
||||
@ -208,15 +182,15 @@ private:
|
||||
/**
|
||||
* Does this TabContext correspond to a browser element?
|
||||
*
|
||||
* If this is true, mOwnAppId must be NO_APP_ID.
|
||||
* If this is true, mOwnApp must be null.
|
||||
*/
|
||||
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.
|
||||
* MutableTabContext is the same as MaybeInvalidTabContext, 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
|
||||
{
|
||||
@ -241,6 +215,65 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* MaybeInvalidTabContext is a simple class that lets you transform an
|
||||
* IPCTabContext into a TabContext.
|
||||
*
|
||||
* The issue is that an IPCTabContext is not necessarily valid; for example, it
|
||||
* might specify an app-id which doesn't exist. So to convert an IPCTabContext
|
||||
* into a TabContext, you construct a MaybeInvalidTabContext, check whether it's
|
||||
* valid, and, if so, read out your TabContext.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* void UseTabContext(const TabContext& aTabContext);
|
||||
*
|
||||
* void CreateTab(const IPCTabContext& aContext) {
|
||||
* MaybeInvalidTabContext tc(aContext);
|
||||
* if (!tc.IsValid()) {
|
||||
* NS_ERROR(nsPrintfCString("Got an invalid IPCTabContext: %s",
|
||||
* tc.GetInvalidReason()));
|
||||
* return;
|
||||
* }
|
||||
* UseTabContext(tc.GetTabContext());
|
||||
* }
|
||||
*/
|
||||
class MaybeInvalidTabContext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor copies the information in aContext and sets IsValid() as
|
||||
* appropriate.
|
||||
*/
|
||||
MaybeInvalidTabContext(const IPCTabContext& aContext);
|
||||
|
||||
/**
|
||||
* Was the IPCTabContext we received in our constructor valid?
|
||||
*/
|
||||
bool IsValid();
|
||||
|
||||
/**
|
||||
* If IsValid(), this function returns null. Otherwise, it returns a
|
||||
* human-readable string indicating why the IPCTabContext passed to our
|
||||
* constructor was not valid.
|
||||
*/
|
||||
const char* GetInvalidReason();
|
||||
|
||||
/**
|
||||
* If IsValid(), this function returns a reference to a TabContext
|
||||
* corresponding to the IPCTabContext passed to our constructor. If
|
||||
* !IsValid(), this function crashes.
|
||||
*/
|
||||
const TabContext& GetTabContext();
|
||||
|
||||
private:
|
||||
MaybeInvalidTabContext(const MaybeInvalidTabContext&) MOZ_DELETE;
|
||||
MaybeInvalidTabContext& operator=(const MaybeInvalidTabContext&) MOZ_DELETE;
|
||||
|
||||
const char* mInvalidReason;
|
||||
MutableTabContext mTabContext;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user