Bug 714861 - Run <iframe mozbrowser> in a separate process (disabled by default). r=cjones,bz,tn,smaug

This commit is contained in:
Justin Lebar 2012-04-25 11:29:28 -04:00
Родитель c01b046b59
Коммит bdcf3134ed
11 изменённых файлов: 167 добавлений и 51 удалений

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

@ -425,9 +425,10 @@ pref("browser.link.open_newwindow", 3);
// 2: don't divert window.open with features
pref("browser.link.open_newwindow.restriction", 0);
// Enable browser frame
// Enable browser frames, but not OOP.
pref("dom.mozBrowserFramesEnabled", true);
pref("dom.mozBrowserFramesWhitelist", "http://homescreen.gaiamobile.org,http://browser.gaiamobile.org");
pref("dom.ipc.tabs.disabled", true);
// Temporary permission hack for WebSMS
pref("dom.sms.enabled", true);

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

@ -457,8 +457,13 @@ nsFrameLoader::ReallyStartLoadingInternal()
}
}
// FIXME get error codes from child
mRemoteBrowser->LoadURL(mURIToLoad);
if (mRemoteBrowserShown || ShowRemoteFrame(nsIntSize(0, 0))) {
// FIXME get error codes from child
mRemoteBrowser->LoadURL(mURIToLoad);
} else {
NS_WARNING("[nsFrameLoader] ReallyStartLoadingInternal tried but couldn't show remote browser.\n");
}
return NS_OK;
}
@ -912,6 +917,18 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size)
// cross-process layers; need to figure out what behavior we really
// want here. For now, hack.
if (!mRemoteBrowserShown) {
if (!mOwnerContent ||
!mOwnerContent->GetCurrentDoc()) {
return false;
}
nsRefPtr<layers::LayerManager> layerManager =
nsContentUtils::LayerManagerForDocument(mOwnerContent->GetCurrentDoc());
if (!layerManager) {
// This is just not going to work.
return false;
}
mRemoteBrowser->Show(size);
mRemoteBrowserShown = true;
@ -1355,19 +1372,27 @@ nsFrameLoader::SetOwnerContent(Element* aContent)
}
}
bool
nsFrameLoader::OwnerIsBrowserFrame()
{
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
bool isBrowser = false;
if (browserFrame) {
browserFrame->GetReallyIsBrowser(&isBrowser);
}
return isBrowser;
}
bool
nsFrameLoader::ShouldUseRemoteProcess()
{
// Check for *disabled* multi-process first: environment, pref
// Then check for *enabled* multi-process attribute
// Default is not-remote.
if (PR_GetEnv("MOZ_DISABLE_OOP_TABS") ||
Preferences::GetBool("dom.ipc.tabs.disabled", false)) {
return false;
}
return (bool) mOwnerContent->AttrValueIs(kNameSpaceID_None,
return OwnerIsBrowserFrame() ||
(bool) mOwnerContent->AttrValueIs(kNameSpaceID_None,
nsGkAtoms::Remote,
nsGkAtoms::_true,
eCaseMatters);
@ -1842,24 +1867,27 @@ nsFrameLoader::TryRemoteBrowser()
nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(parentAsWebNav));
PRInt32 parentType;
parentAsItem->GetItemType(&parentType);
// <iframe mozbrowser> gets to skip these checks.
if (!OwnerIsBrowserFrame()) {
PRInt32 parentType;
parentAsItem->GetItemType(&parentType);
if (parentType != nsIDocShellTreeItem::typeChrome) {
return false;
}
if (parentType != nsIDocShellTreeItem::typeChrome) {
return false;
}
if (!mOwnerContent->IsXUL()) {
return false;
}
if (!mOwnerContent->IsXUL()) {
return false;
}
nsAutoString value;
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
nsAutoString value;
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
if (!value.LowerCaseEqualsLiteral("content") &&
!StringBeginsWith(value, NS_LITERAL_STRING("content-"),
nsCaseInsensitiveStringComparator())) {
return false;
if (!value.LowerCaseEqualsLiteral("content") &&
!StringBeginsWith(value, NS_LITERAL_STRING("content-"),
nsCaseInsensitiveStringComparator())) {
return false;
}
}
PRUint32 chromeFlags = 0;
@ -2131,6 +2159,19 @@ nsFrameLoader::GetRootContentView(nsIContentView** aContentView)
return NS_OK;
}
static already_AddRefed<nsIDocShell>
GetRootDocShell(nsIDocument *aDocument)
{
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aDocument->GetWindow());
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(webNav);
NS_ENSURE_TRUE(treeItem, NULL);
nsCOMPtr<nsIDocShellTreeItem> rootItem;
treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
nsCOMPtr<nsIDocShell> rootDocShell = do_QueryInterface(rootItem);
return rootDocShell.forget();
}
nsresult
nsFrameLoader::EnsureMessageManager()
{
@ -2159,8 +2200,12 @@ nsFrameLoader::EnsureMessageManager()
NS_ENSURE_STATE(cx);
nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
do_QueryInterface(mOwnerContent->OwnerDoc()->GetWindow());
NS_ENSURE_STATE(chromeWindow);
do_QueryInterface(OwnerDoc()->GetWindow());
if (!chromeWindow) {
nsCOMPtr<nsIDocShell> rootDocShell = GetRootDocShell(OwnerDoc());
nsCOMPtr<nsIDOMWindow> rootWindow = do_GetInterface(rootDocShell);
chromeWindow = do_GetInterface(rootWindow);
}
nsCOMPtr<nsIChromeFrameMessageManager> parentManager;
chromeWindow->GetMessageManager(getter_AddRefs(parentManager));

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

@ -295,6 +295,12 @@ private:
bool ShouldUseRemoteProcess();
/**
* Is this a frameloader for a bona fide <iframe mozbrowser>? (I.e., does
* the frame return true for nsIMozBrowserFrame::GetReallyIsBrowser()?)
*/
bool OwnerIsBrowserFrame();
/**
* If we are an IPC frame, set mRemoteFrame. Otherwise, create and
* initialize mDocShell.

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

@ -100,6 +100,8 @@
#include "nsIDOMUIEvent.h"
#include "nsDOMDragEvent.h"
#include "nsIDOMNSEditableElement.h"
#include "nsIDOMMozBrowserFrame.h"
#include "nsIMozBrowserFrame.h"
#include "nsCaret.h"
@ -1701,12 +1703,30 @@ nsEventStateManager::DispatchCrossProcessEvent(nsEvent* aEvent, nsIFrameLoader*
bool
nsEventStateManager::IsRemoteTarget(nsIContent* target) {
return target &&
(target->Tag() == nsGkAtoms::browser ||
target->Tag() == nsGkAtoms::iframe) &&
target->IsXUL() &&
target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
nsGkAtoms::_true, eIgnoreCase);
if (!target) {
return false;
}
// <browser/iframe remote=true> from XUL
if ((target->Tag() == nsGkAtoms::browser ||
target->Tag() == nsGkAtoms::iframe) &&
target->IsXUL() &&
target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
nsGkAtoms::_true, eIgnoreCase)) {
return true;
}
// <frame/iframe mozbrowser>
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(target);
if (browserFrame) {
bool isRemote = false;
browserFrame->GetReallyIsBrowser(&isRemote);
if (isRemote) {
return true;
}
}
return false;
}

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

@ -233,9 +233,9 @@ ConsoleListener::Observe(nsIConsoleMessage* aMessage)
ContentChild* ContentChild::sSingleton;
ContentChild::ContentChild()
: mID(PRUint64(-1))
#ifdef ANDROID
: mScreenSize(0, 0)
, mID(PRUint64(-1))
, mScreenSize(0, 0)
#endif
{
// This process is a content process, so it's clearly running in

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

@ -201,8 +201,6 @@ private:
gfxIntSize mScreenSize;
#endif
AppInfo mAppInfo;
/**
* An ID unique to the process containing our corresponding
* content parent.
@ -212,6 +210,8 @@ private:
*/
PRUint64 mID;
AppInfo mAppInfo;
static ContentChild* sSingleton;
DISALLOW_EVIL_CONSTRUCTORS(ContentChild);

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

@ -70,6 +70,7 @@
#include "nsIViewManager.h"
#include "mozilla/unused.h"
#include "nsDebug.h"
#include "nsPrintfCString.h"
using namespace mozilla::dom;
using namespace mozilla::ipc;
@ -93,6 +94,7 @@ TabParent::TabParent()
, mIMESeqno(0)
, mDPI(0)
, mActive(false)
, mShown(false)
{
}
@ -104,13 +106,7 @@ void
TabParent::SetOwnerElement(nsIDOMElement* aElement)
{
mFrameElement = aElement;
// Cache the DPI of the screen, since we may lose the element/widget later
if (aElement) {
nsCOMPtr<nsIWidget> widget = GetWidget();
NS_ABORT_IF_FALSE(widget, "Non-null OwnerElement must provide a widget!");
mDPI = widget->GetDPI();
}
TryCacheDPI();
}
void
@ -197,6 +193,16 @@ TabParent::AnswerCreateWindow(PBrowserParent** retval)
void
TabParent::LoadURL(nsIURI* aURI)
{
if (!mShown) {
nsCAutoString spec;
if (aURI) {
aURI->GetSpec(spec);
}
NS_WARNING(nsPrintfCString(1024, "TabParent::LoadURL(%s) called before "
"Show(). Ignoring LoadURL.\n", spec.get()).get());
return;
}
nsCString spec;
aURI->GetSpec(spec);
@ -207,6 +213,7 @@ void
TabParent::Show(const nsIntSize& size)
{
// sigh
mShown = true;
unused << SendShow(size);
}
@ -621,6 +628,7 @@ TabParent::RecvSetInputContext(const PRInt32& aIMEEnabled,
bool
TabParent::RecvGetDPI(float* aValue)
{
TryCacheDPI();
NS_ABORT_IF_FALSE(mDPI > 0,
"Must not ask for DPI before OwnerElement is received!");
*aValue = mDPI;
@ -848,6 +856,19 @@ TabParent::GetFrameLoader() const
return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nsnull;
}
void
TabParent::TryCacheDPI()
{
if (mDPI > 0) {
return;
}
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget) {
mDPI = widget->GetDPI();
}
}
already_AddRefed<nsIWidget>
TabParent::GetWidget() const
{
@ -859,7 +880,8 @@ TabParent::GetWidget() const
if (!frame)
return nsnull;
return nsCOMPtr<nsIWidget>(frame->GetNearestWidget()).forget();
nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget();
return widget.forget();
}
} // namespace tabs

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

@ -233,10 +233,12 @@ protected:
float mDPI;
bool mActive;
bool mShown;
private:
already_AddRefed<nsFrameLoader> GetFrameLoader() const;
already_AddRefed<nsIWidget> GetWidget() const;
void TryCacheDPI();
};
} // namespace dom

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

@ -21,6 +21,15 @@ const browserFrameHelpers = {
}
},
'getOOPDisabledPref': function() {
try {
return SpecialPowers.getBoolPref('dom.ipc.tabs.disabled');
}
catch(e) {
return undefined;
}
},
'setEnabledPref': function(enabled) {
if (enabled !== undefined) {
SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', enabled);
@ -39,6 +48,15 @@ const browserFrameHelpers = {
}
},
'setOOPDisabledPref': function(value) {
if (value !== undefined) {
SpecialPowers.setBoolPref('dom.ipc.tabs.disabled', value);
}
else {
SpecialPowers.clearUserPref('dom.ipc.tabs.disabled');
}
},
'addToWhitelist': function() {
var whitelist = browserFrameHelpers.getWhitelistPref();
whitelist += ', http://' + window.location.host + ', ';
@ -48,10 +66,12 @@ const browserFrameHelpers = {
'restoreOriginalPrefs': function() {
browserFrameHelpers.setEnabledPref(browserFrameHelpers.origEnabledPref);
browserFrameHelpers.setWhitelistPref(browserFrameHelpers.origWhitelistPref);
browserFrameHelpers.setOOPDisabledPref(browserFrameHelpers.origOOPDisabledPref);
},
'origEnabledPref': null,
'origWhitelistPref': null,
'origOOPDisabledPref': null,
// Two basically-empty pages from two different domains you can load.
'emptyPage1': 'http://example.com' +
@ -64,6 +84,11 @@ const browserFrameHelpers = {
browserFrameHelpers.origEnabledPref = browserFrameHelpers.getEnabledPref();
browserFrameHelpers.origWhitelistPref = browserFrameHelpers.getWhitelistPref();
browserFrameHelpers.origOOPDisabledPref = browserFrameHelpers.getOOPDisabledPref();
// Set OOPDisabledPref to true, because none of these tests pass with OOP
// browser frames, at the moment.
browserFrameHelpers.setOOPDisabledPref(true);
addEventListener('unload', function() {
browserFrameHelpers.restoreOriginalPrefs();

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

@ -52,6 +52,7 @@
#include "nsViewportFrame.h"
#include "nsSubDocumentFrame.h"
#include "nsIObserver.h"
#include "nsContentUtils.h"
typedef nsContentView::ViewConfig ViewConfig;
using namespace mozilla::layers;
@ -641,7 +642,9 @@ RenderFrameParent::AllocPLayers(LayerManager::LayersBackend* aBackendType)
*aBackendType = LayerManager::LAYERS_NONE;
return nsnull;
}
LayerManager* lm = GetLayerManager();
nsRefPtr<LayerManager> lm =
nsContentUtils::LayerManagerForDocument(mFrameLoader->OwnerDoc());
ShadowLayerManager* slm = lm->AsShadowManager();
if (!slm) {
*aBackendType = LayerManager::LAYERS_NONE;
@ -692,13 +695,6 @@ RenderFrameParent::BuildViewMap()
mContentViews = newContentViews;
}
LayerManager*
RenderFrameParent::GetLayerManager() const
{
nsIDocument* doc = mFrameLoader->OwnerDoc();
return doc->GetShell()->GetLayerManager();
}
ShadowLayersParent*
RenderFrameParent::GetShadowLayers() const
{

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

@ -111,7 +111,6 @@ protected:
private:
void BuildViewMap();
LayerManager* GetLayerManager() const;
ShadowLayersParent* GetShadowLayers() const;
ContainerLayer* GetRootLayer() const;