Bug 776649, part 2: Refactor content-process/browser creation to use mozIApplication for passing app info. r=jlebar

This commit is contained in:
Chris Jones 2012-08-08 19:58:06 -07:00
Родитель 5fa558d5d4
Коммит d870f5de82
10 изменённых файлов: 148 добавлений и 71 удалений

Просмотреть файл

@ -13,6 +13,7 @@
#include "prenv.h"
#include "mozIApplication.h"
#include "nsIDOMHTMLIFrameElement.h"
#include "nsIDOMHTMLFrameElement.h"
#include "nsIDOMMozBrowserFrame.h"
@ -31,6 +32,7 @@
#include "nsIDocShellTreeNode.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDocShellLoadInfo.h"
#include "nsIDOMApplicationRegistry.h"
#include "nsIBaseWindow.h"
#include "nsContentUtils.h"
#include "nsIXPConnect.h"
@ -1973,9 +1975,8 @@ nsFrameLoader::TryRemoteBrowser()
return false;
}
PRUint32 appId = 0;
bool isBrowserElement = false;
nsCOMPtr<mozIApplication> app;
if (OwnerIsBrowserFrame()) {
isBrowserElement = true;
@ -1989,24 +1990,21 @@ nsFrameLoader::TryRemoteBrowser()
return false;
}
appsService->GetAppLocalIdByManifestURL(manifest, &appId);
// If the frame is actually an app, we should not mark it as a browser.
if (appId != nsIScriptSecurityManager::NO_APP_ID) {
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;
}
}
}
// If our owner has no app manifest URL, then this is equivalent to
// ContentParent::GetNewOrUsed().
nsAutoString appManifest;
GetOwnerAppManifestURL(appManifest);
ContentParent* parent = ContentParent::GetForApp(appManifest);
NS_ASSERTION(parent->IsAlive(), "Process parent should be alive; something is very wrong!");
mRemoteBrowser = parent->CreateTab(chromeFlags, isBrowserElement, appId);
if (mRemoteBrowser) {
if ((mRemoteBrowser = ContentParent::CreateBrowser(app, isBrowserElement))) {
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mOwnerContent);
mRemoteBrowser->SetOwnerElement(element);
@ -2019,8 +2017,8 @@ nsFrameLoader::TryRemoteBrowser()
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
mChildHost = parent;
mChildHost = static_cast<ContentParent*>(mRemoteBrowser->Manager());
}
return true;
}

Просмотреть файл

@ -39,6 +39,7 @@
#include "nsIObserverService.h"
#include "nsTObserverArray.h"
#include "nsIObserver.h"
#include "nsIScriptSecurityManager.h"
#include "nsServiceManagerUtils.h"
#include "nsXULAppAPI.h"
#include "nsWeakReference.h"
@ -402,10 +403,11 @@ ContentChild::AllocPCompositor(mozilla::ipc::Transport* aTransport,
PBrowserChild*
ContentChild::AllocPBrowser(const PRUint32& aChromeFlags,
const bool& aIsBrowserElement,
const PRUint32& aAppId)
const bool& aIsBrowserElement, const AppId& aApp)
{
nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement, aAppId);
PRUint32 appId = aApp.get_uint32_t();
nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement,
appId);
return NS_SUCCEEDED(iframe->Init()) ? iframe.forget().get() : NULL;
}

Просмотреть файл

@ -68,7 +68,7 @@ public:
virtual PBrowserChild* AllocPBrowser(const PRUint32& aChromeFlags,
const bool& aIsBrowserElement,
const PRUint32& aAppId);
const AppId& aAppId);
virtual bool DeallocPBrowser(PBrowserChild*);
virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequest(const DeviceStorageParams&);

Просмотреть файл

@ -20,6 +20,7 @@
#include "IDBFactory.h"
#include "IndexedDBParent.h"
#include "IndexedDatabaseManager.h"
#include "mozIApplication.h"
#include "mozilla/Preferences.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
@ -49,8 +50,10 @@
#include "nsFrameMessageManager.h"
#include "nsHashPropertyBag.h"
#include "nsIAlertsService.h"
#include "nsIAppsService.h"
#include "nsIClipboard.h"
#include "nsIConsoleService.h"
#include "nsIDOMApplicationRegistry.h"
#include "nsIDOMGeoGeolocation.h"
#include "nsIDOMWindow.h"
#include "nsIFilePicker.h"
@ -59,6 +62,7 @@
#include "nsIPresShell.h"
#include "nsIRemoteBlob.h"
#include "nsIScriptError.h"
#include "nsIScriptSecurityManager.h"
#include "nsISupportsPrimitives.h"
#include "nsIWindowWatcher.h"
#include "nsMemoryReporterManager.h"
@ -149,7 +153,7 @@ nsTArray<ContentParent*>* ContentParent::gPrivateContent;
// The first content child has ID 1, so the chrome process can have ID 0.
static PRUint64 gContentChildID = 1;
ContentParent*
/*static*/ ContentParent*
ContentParent::GetNewOrUsed()
{
if (!gNonAppContentParents)
@ -165,7 +169,7 @@ ContentParent::GetNewOrUsed()
NS_ASSERTION(p->IsAlive(), "Non-alive contentparent in gNonAppContentParents?");
return p;
}
nsRefPtr<ContentParent> p =
new ContentParent(/* appManifestURL = */ EmptyString());
p->Init();
@ -173,11 +177,20 @@ ContentParent::GetNewOrUsed()
return p;
}
ContentParent*
ContentParent::GetForApp(const nsAString& aAppManifestURL)
/*static*/ TabParent*
ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement)
{
if (aAppManifestURL.IsEmpty()) {
return GetNewOrUsed();
if (!aApp) {
if (ContentParent* cp = GetNewOrUsed()) {
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));
}
return nullptr;
}
if (!gAppContentParents) {
@ -187,14 +200,39 @@ ContentParent::GetForApp(const nsAString& aAppManifestURL)
}
// Each app gets its own ContentParent instance.
ContentParent* p = gAppContentParents->Get(aAppManifestURL);
if (!p) {
p = new ContentParent(aAppManifestURL);
p->Init();
gAppContentParents->Put(aAppManifestURL, p);
nsAutoString manifestURL;
if (NS_FAILED(aApp->GetManifestURL(manifestURL))) {
NS_ERROR("Failed to get manifest URL");
return nullptr;
}
return p;
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.
PRUint32 appId;
if (NS_FAILED(appsService->GetAppLocalIdByManifestURL(manifestURL, &appId))) {
NS_ERROR("Failed to get local app ID");
return nullptr;
}
ContentParent* p = gAppContentParents->Get(manifestURL);
if (!p) {
p = new ContentParent(manifestURL);
p->Init();
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));
}
static PLDHashOperator
@ -455,12 +493,6 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
}
TabParent*
ContentParent::CreateTab(PRUint32 aChromeFlags, bool aIsBrowserElement, PRUint32 aAppId)
{
return static_cast<TabParent*>(SendPBrowserConstructor(aChromeFlags, aIsBrowserElement, aAppId));
}
void
ContentParent::NotifyTabDestroyed(PBrowserParent* aTab)
{
@ -862,22 +894,40 @@ ContentParent::AllocPCompositor(mozilla::ipc::Transport* aTransport,
PBrowserParent*
ContentParent::AllocPBrowser(const PRUint32& aChromeFlags,
const bool& aIsBrowserElement,
const PRUint32& aAppId)
const bool& aIsBrowserElement, const AppId& aApp)
{
TabParent* parent = new TabParent();
if (parent){
// 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());
// 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");
return nullptr;
}
TabParent* parent = new TabParent(opener ? opener->GetApp() : nullptr,
aIsBrowserElement);
// We release this ref in DeallocPBrowser()
NS_ADDREF(parent);
}
return parent;
return parent;
}
bool
ContentParent::DeallocPBrowser(PBrowserParent* frame)
{
TabParent* parent = static_cast<TabParent*>(frame);
NS_RELEASE(parent);
return true;
TabParent* parent = static_cast<TabParent*>(frame);
NS_RELEASE(parent);
return true;
}
PDeviceStorageRequestParent*

Просмотреть файл

@ -26,6 +26,7 @@
#include "nsInterfaceHashtable.h"
#include "nsHashKeys.h"
class mozIApplication;
class nsFrameMessageManager;
class nsIDOMBlob;
@ -60,13 +61,16 @@ public:
static ContentParent* GetNewOrUsed();
/**
* Get or create a content process for the given app. A given app
* (identified by its manifest URL) gets one process all to itself.
* 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.
*
* If the given manifest is the empty string, then this method is equivalent
* to GetNewOrUsed().
* Currently apps are given their own process, and browser tabs
* share processes.
*/
static ContentParent* GetForApp(const nsAString& aManifestURL);
static TabParent* CreateBrowser(mozIApplication* aApp,
bool aIsBrowserFrame);
static void GetAll(nsTArray<ContentParent*>& aArray);
NS_DECL_ISUPPORTS
@ -74,14 +78,6 @@ public:
NS_DECL_NSITHREADOBSERVER
NS_DECL_NSIDOMGEOPOSITIONCALLBACK
/**
* Create a new tab.
*
* |aIsBrowserElement| indicates whether this tab is part of an
* <iframe mozbrowser>.
* |aAppId| indicates which app the tab belongs to.
*/
TabParent* CreateTab(PRUint32 aChromeFlags, bool aIsBrowserElement, PRUint32 aAppId);
/** Notify that a tab was destroyed during normal operation. */
void NotifyTabDestroyed(PBrowserParent* aTab);
@ -143,7 +139,9 @@ private:
PCompositorParent* AllocPCompositor(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags, const bool& aIsBrowserElement, const PRUint32& aAppId);
virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags,
const bool& aIsBrowserElement,
const AppId& aApp);
virtual bool DeallocPBrowser(PBrowserParent* frame);
virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequest(const DeviceStorageParams&);

Просмотреть файл

@ -122,6 +122,11 @@ union BlobConstructorParams
MysteryBlobConstructorParams;
};
union AppId {
uint32_t;
nullable PBrowser;
};
rpc protocol PContent
{
parent opens PCompositor;
@ -145,9 +150,16 @@ 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.
async PBrowser(PRUint32 chromeFlags, bool isBrowserElement, PRUint32 appId);
// TabChild::BrowserFrameProvideWindow, 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(PRUint32 chromeFlags, bool isBrowserElement, AppId appId);
async PBlob(BlobConstructorParams params);

Просмотреть файл

@ -422,10 +422,13 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
{
*aReturn = nullptr;
nsRefPtr<TabChild> newChild =
static_cast<TabChild*>(Manager()->SendPBrowserConstructor(
/* aChromeFlags = */ 0, mIsBrowserElement, mAppId));
PRUint32 chromeFlags = 0;
nsRefPtr<TabChild> newChild = new TabChild(chromeFlags,
mIsBrowserElement, mAppId);
static_cast<TabChild*>(Manager()->SendPBrowserConstructor(
// We release this ref in DeallocPBrowserChild
nsRefPtr<TabChild>(newChild).forget().get(),
chromeFlags, mIsBrowserElement, this));
nsCAutoString spec;
if (aURI) {
aURI->GetSpec(spec);

Просмотреть файл

@ -158,6 +158,8 @@ public:
virtual ~TabChild();
nsresult Init();
PRUint32 GetAppId() { return mAppId; }
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBBROWSERCHROME
NS_DECL_NSIWEBBROWSERCHROME2

Просмотреть файл

@ -11,6 +11,7 @@
#include "Blob.h"
#include "IDBFactory.h"
#include "IndexedDBParent.h"
#include "mozIApplication.h"
#include "mozilla/BrowserElementParent.h"
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
#include "mozilla/dom/ContentParent.h"
@ -27,6 +28,7 @@
#include "nsFocusManager.h"
#include "nsFrameLoader.h"
#include "nsIContent.h"
#include "nsIDOMApplicationRegistry.h"
#include "nsIDOMElement.h"
#include "nsIDOMEvent.h"
#include "nsIDOMEventTarget.h"
@ -36,6 +38,7 @@
#include "nsIPromptFactory.h"
#include "nsIURI.h"
#include "nsIMozBrowserFrame.h"
#include "nsIScriptSecurityManager.h"
#include "nsIViewManager.h"
#include "nsIWidget.h"
#include "nsIWindowWatcher.h"
@ -52,6 +55,7 @@ using namespace mozilla::dom;
using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::layout;
using namespace mozilla::services;
using namespace mozilla::widget;
using namespace mozilla::dom::indexedDB;
@ -66,8 +70,9 @@ TabParent *TabParent::mIMETabParent = nullptr;
NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
TabParent::TabParent()
TabParent::TabParent(mozIApplication* aApp, bool aIsBrowserElement)
: mFrameElement(NULL)
, mApp(aApp)
, mIMESelectionAnchor(0)
, mIMESelectionFocus(0)
, mIMEComposing(false)
@ -76,6 +81,7 @@ TabParent::TabParent()
, mIMESeqno(0)
, mDPI(0)
, mActive(false)
, mIsBrowserElement(aIsBrowserElement)
, mShown(false)
{
}

Просмотреть файл

@ -24,6 +24,7 @@
struct gfxMatrix;
struct JSContext;
struct JSObject;
class mozIApplication;
class nsFrameLoader;
class nsIDOMElement;
class nsIURI;
@ -53,7 +54,7 @@ class TabParent : public PBrowserParent
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
public:
TabParent();
TabParent(mozIApplication* aApp, bool aIsBrowserElement);
virtual ~TabParent();
nsIDOMElement* GetOwnerElement() { return mFrameElement; }
void SetOwnerElement(nsIDOMElement* aElement);
@ -62,6 +63,9 @@ public:
mBrowserDOMWindow = aBrowserDOMWindow;
}
mozIApplication* GetApp() { return mApp; }
bool IsBrowserElement() { return mIsBrowserElement; }
void Destroy();
virtual bool RecvMoveFocus(const bool& aForward);
@ -225,6 +229,7 @@ protected:
uint64_t* aLayersId) MOZ_OVERRIDE;
virtual bool DeallocPRenderFrame(PRenderFrameParent* aFrame) MOZ_OVERRIDE;
nsCOMPtr<mozIApplication> mApp;
// IME
static TabParent *mIMETabParent;
nsString mIMECacheText;
@ -240,6 +245,7 @@ protected:
float mDPI;
bool mActive;
bool mIsBrowserElement;
bool mShown;
private: