Bug 1172870 - Part 1 - Move PBrowser::CreateWindow to PContent. r=smaug

This commit is contained in:
Catalin Badea 2015-10-30 01:30:57 +02:00
Родитель 55039de64c
Коммит bad419762d
10 изменённых файлов: 501 добавлений и 457 удалений

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

@ -47,6 +47,7 @@
#include "mozilla/layers/ImageBridgeChild.h" #include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/PCompositorChild.h" #include "mozilla/layers/PCompositorChild.h"
#include "mozilla/layers/SharedBufferManagerChild.h" #include "mozilla/layers/SharedBufferManagerChild.h"
#include "mozilla/layout/RenderFrameChild.h"
#include "mozilla/net/NeckoChild.h" #include "mozilla/net/NeckoChild.h"
#include "mozilla/plugins/PluginInstanceParent.h" #include "mozilla/plugins/PluginInstanceParent.h"
#include "mozilla/plugins/PluginModuleParent.h" #include "mozilla/plugins/PluginModuleParent.h"
@ -216,6 +217,7 @@ using namespace mozilla::gmp;
using namespace mozilla::hal_sandbox; using namespace mozilla::hal_sandbox;
using namespace mozilla::ipc; using namespace mozilla::ipc;
using namespace mozilla::layers; using namespace mozilla::layers;
using namespace mozilla::layout;
using namespace mozilla::net; using namespace mozilla::net;
using namespace mozilla::jsipc; using namespace mozilla::jsipc;
using namespace mozilla::psm; using namespace mozilla::psm;
@ -608,7 +610,8 @@ ContentChild::~ContentChild()
NS_INTERFACE_MAP_BEGIN(ContentChild) NS_INTERFACE_MAP_BEGIN(ContentChild)
NS_INTERFACE_MAP_ENTRY(nsIContentChild) NS_INTERFACE_MAP_ENTRY(nsIContentChild)
NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentChild)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
bool bool
@ -741,6 +744,149 @@ ContentChild::SetProcessName(const nsAString& aName, bool aDontOverride)
} }
} }
NS_IMETHODIMP
ContentChild::ProvideWindow(nsIDOMWindow* aParent,
uint32_t aChromeFlags,
bool aCalledFromJS,
bool aPositionSpecified,
bool aSizeSpecified,
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool* aWindowIsNew,
nsIDOMWindow** aReturn)
{
return ProvideWindowCommon(nullptr, aParent, false, aChromeFlags,
aCalledFromJS, aPositionSpecified,
aSizeSpecified, aURI, aName, aFeatures,
aWindowIsNew, aReturn);
}
nsresult
ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
nsIDOMWindow* aParent,
bool aIframeMoz,
uint32_t aChromeFlags,
bool aCalledFromJS,
bool aPositionSpecified,
bool aSizeSpecified,
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool* aWindowIsNew,
nsIDOMWindow** aReturn)
{
MOZ_ASSERT(aTabOpener);
*aReturn = nullptr;
const TabId openerTabId = aTabOpener->GetTabId();
PopupIPCTabContext context;
context.opener() = openerTabId;
context.isBrowserElement() = aTabOpener->IsBrowserElement();
IPCTabContext ipcContext(context);
TabId tabId;
SendAllocateTabId(openerTabId,
ipcContext,
GetID(),
&tabId);
RefPtr<TabChild> newChild = new TabChild(this, tabId,
*aTabOpener, aChromeFlags);
if (NS_FAILED(newChild->Init())) {
return NS_ERROR_ABORT;
}
context.opener() = aTabOpener;
unused << SendPBrowserConstructor(
// We release this ref in DeallocPBrowserChild
RefPtr<TabChild>(newChild).forget().take(),
tabId, IPCTabContext(context), aChromeFlags,
GetID(), IsForApp(), IsForBrowser());
nsAutoCString spec;
if (aURI) {
aURI->GetSpec(spec);
}
NS_ConvertUTF8toUTF16 url(spec);
nsString name(aName);
nsAutoCString features(aFeatures);
nsTArray<FrameScriptInfo> frameScripts;
nsCString urlToLoad;
if (aIframeMoz) {
MOZ_ASSERT(aTabOpener);
newChild->SendBrowserFrameOpenWindow(aTabOpener, url, name,
NS_ConvertUTF8toUTF16(features),
aWindowIsNew);
} else {
nsCOMPtr<nsPIDOMWindow> opener = do_QueryInterface(aParent);
nsCOMPtr<nsIDocument> doc = opener->GetDoc();
nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
if (!baseURI) {
NS_ERROR("nsIDocument didn't return a base URI");
return NS_ERROR_FAILURE;
}
nsAutoCString baseURIString;
baseURI->GetSpec(baseURIString);
nsresult rv;
if (!SendCreateWindow(aTabOpener, newChild,
aChromeFlags, aCalledFromJS, aPositionSpecified,
aSizeSpecified, url,
name, features,
NS_ConvertUTF8toUTF16(baseURIString),
&rv,
aWindowIsNew,
&frameScripts,
&urlToLoad)) {
return NS_ERROR_NOT_AVAILABLE;
}
if (NS_FAILED(rv)) {
return rv;
}
}
if (!*aWindowIsNew) {
PBrowserChild::Send__delete__(newChild);
return NS_ERROR_ABORT;
}
TextureFactoryIdentifier textureFactoryIdentifier;
uint64_t layersId = 0;
PRenderFrameChild* renderFrame = newChild->SendPRenderFrameConstructor();
newChild->SendGetRenderFrameInfo(renderFrame,
&textureFactoryIdentifier,
&layersId);
if (layersId == 0) { // if renderFrame is invalid.
PRenderFrameChild::Send__delete__(renderFrame);
renderFrame = nullptr;
}
// Unfortunately we don't get a window unless we've shown the frame. That's
// pretty bogus; see bug 763602.
newChild->DoFakeShow(textureFactoryIdentifier, layersId, renderFrame);
for (size_t i = 0; i < frameScripts.Length(); i++) {
FrameScriptInfo& info = frameScripts[i];
if (!newChild->RecvLoadRemoteScript(info.url(), info.runInGlobalScope())) {
MOZ_CRASH();
}
}
if (!urlToLoad.IsEmpty()) {
newChild->RecvLoadURL(urlToLoad, BrowserConfiguration());
}
nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation());
win.forget(aReturn);
return NS_OK;
}
void void
ContentChild::GetProcessName(nsAString& aName) ContentChild::GetProcessName(nsAString& aName)
{ {
@ -2748,7 +2894,8 @@ ContentChild::RecvShutdown()
nsCOMPtr<nsIObserverService> os = services::GetObserverService(); nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) { if (os) {
os->NotifyObservers(this, "content-child-shutdown", nullptr); os->NotifyObservers(static_cast<nsIContentChild*>(this),
"content-child-shutdown", nullptr);
} }
GetIPCChannel()->SetAbortOnError(false); GetIPCChannel()->SetAbortOnError(false);

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

@ -17,6 +17,7 @@
#include "nsTHashtable.h" #include "nsTHashtable.h"
#include "nsWeakPtr.h" #include "nsWeakPtr.h"
#include "nsIWindowProvider.h"
struct ChromePackage; struct ChromePackage;
@ -47,6 +48,7 @@ class ClonedMessageData;
class TabChild; class TabChild;
class ContentChild final : public PContentChild class ContentChild final : public PContentChild
, public nsIWindowProvider
, public nsIContentChild , public nsIContentChild
{ {
typedef mozilla::dom::ClonedMessageData ClonedMessageData; typedef mozilla::dom::ClonedMessageData ClonedMessageData;
@ -55,6 +57,8 @@ class ContentChild final : public PContentChild
typedef mozilla::ipc::URIParams URIParams; typedef mozilla::ipc::URIParams URIParams;
public: public:
NS_DECL_NSIWINDOWPROVIDER
ContentChild(); ContentChild();
virtual ~ContentChild(); virtual ~ContentChild();
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
@ -71,6 +75,20 @@ public:
nsCString vendor; nsCString vendor;
}; };
nsresult
ProvideWindowCommon(TabChild* aTabOpener,
nsIDOMWindow* aOpener,
bool aIframeMoz,
uint32_t aChromeFlags,
bool aCalledFromJS,
bool aPositionSpecified,
bool aSizeSpecified,
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool* aWindowIsNew,
nsIDOMWindow** aReturn);
bool Init(MessageLoop* aIOLoop, bool Init(MessageLoop* aIOLoop,
base::ProcessId aParentPid, base::ProcessId aParentPid,
IPC::Channel* aChannel); IPC::Channel* aChannel);

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

@ -9,6 +9,7 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "ContentParent.h" #include "ContentParent.h"
#include "TabParent.h"
#if defined(ANDROID) || defined(LINUX) #if defined(ANDROID) || defined(LINUX)
# include <sys/time.h> # include <sys/time.h>
@ -144,7 +145,13 @@
#include "nsISystemMessagesInternal.h" #include "nsISystemMessagesInternal.h"
#include "nsITimer.h" #include "nsITimer.h"
#include "nsIURIFixup.h" #include "nsIURIFixup.h"
#include "nsIWindowMediator.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIXULWindow.h"
#include "nsIDOMChromeWindow.h"
#include "nsIWindowWatcher.h" #include "nsIWindowWatcher.h"
#include "nsPIWindowWatcher.h"
#include "nsWindowWatcher.h"
#include "nsIXULRuntime.h" #include "nsIXULRuntime.h"
#include "gfxDrawable.h" #include "gfxDrawable.h"
#include "ImageOps.h" #include "ImageOps.h"
@ -166,6 +173,7 @@
#include "nsIWebBrowserChrome.h" #include "nsIWebBrowserChrome.h"
#include "nsIDocShell.h" #include "nsIDocShell.h"
#include "nsDocShell.h" #include "nsDocShell.h"
#include "nsOpenURIInFrameParams.h"
#include "mozilla/net/NeckoMessageUtils.h" #include "mozilla/net/NeckoMessageUtils.h"
#include "gfxPrefs.h" #include "gfxPrefs.h"
#include "prio.h" #include "prio.h"
@ -5343,6 +5351,226 @@ ContentParent::DeallocPWebBrowserPersistDocumentParent(PWebBrowserPersistDocumen
return true; return true;
} }
static already_AddRefed<nsPIDOMWindow>
FindMostRecentOpenWindow()
{
nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
windowMediator->GetEnumerator(MOZ_UTF16("navigator:browser"),
getter_AddRefs(windowEnumerator));
nsCOMPtr<nsPIDOMWindow> latest;
bool hasMore = false;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(windowEnumerator->HasMoreElements(&hasMore)));
while (hasMore) {
nsCOMPtr<nsISupports> item;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(windowEnumerator->GetNext(getter_AddRefs(item))));
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(item);
if (window && !window->Closed()) {
latest = window;
}
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(windowEnumerator->HasMoreElements(&hasMore)));
}
return latest.forget();
}
bool
ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
PBrowserParent* aNewTab,
const uint32_t& aChromeFlags,
const bool& aCalledFromJS,
const bool& aPositionSpecified,
const bool& aSizeSpecified,
const nsString& aURI,
const nsString& aName,
const nsCString& aFeatures,
const nsString& aBaseURI,
nsresult* aResult,
bool* aWindowIsNew,
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
nsCString* aURLToLoad)
{
// We always expect to open a new window here. If we don't, it's an error.
*aWindowIsNew = true;
// The content process should never be in charge of computing whether or
// not a window should be private or remote - the parent will do that.
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW));
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW));
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME));
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW));
TabParent* thisTabParent = TabParent::GetFrom(aThisTab);
MOZ_ASSERT(thisTabParent);
if (NS_WARN_IF(thisTabParent->IsBrowserOrApp())) {
return false;
}
nsCOMPtr<nsPIWindowWatcher> pwwatch =
do_GetService(NS_WINDOWWATCHER_CONTRACTID, aResult);
if (NS_WARN_IF(NS_FAILED(*aResult))) {
return true;
}
TabParent* newTab = TabParent::GetFrom(aNewTab);
MOZ_ASSERT(newTab);
// Content has requested that we open this new content window, so
// we must have an opener.
newTab->SetHasContentOpener(true);
nsCOMPtr<nsIContent> frame(do_QueryInterface(thisTabParent->GetOwnerElement()));
nsCOMPtr<nsPIDOMWindow> parent;
if (frame) {
parent = frame->OwnerDoc()->GetWindow();
// If our chrome window is in the process of closing, don't try to open a
// new tab in it.
if (parent && parent->Closed()) {
parent = nullptr;
}
}
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin = thisTabParent->GetBrowserDOMWindow();
// If we haven't found a chrome window to open in, just use the most recently
// opened one.
if (!parent) {
parent = FindMostRecentOpenWindow();
if (NS_WARN_IF(!parent)) {
*aResult = NS_ERROR_FAILURE;
return true;
}
nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(parent);
if (rootChromeWin) {
rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
}
}
int32_t openLocation =
nsWindowWatcher::GetWindowOpenLocation(parent, aChromeFlags, aCalledFromJS,
aPositionSpecified, aSizeSpecified);
MOZ_ASSERT(openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB ||
openLocation == nsIBrowserDOMWindow::OPEN_NEWWINDOW);
// Opening new tabs is the easy case...
if (openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB) {
if (NS_WARN_IF(!browserDOMWin)) {
*aResult = NS_ERROR_FAILURE;
return true;
}
bool isPrivate = false;
nsCOMPtr<nsILoadContext> loadContext = thisTabParent->GetLoadContext();
loadContext->GetUsePrivateBrowsing(&isPrivate);
nsCOMPtr<nsIOpenURIInFrameParams> params = new nsOpenURIInFrameParams();
params->SetReferrer(aBaseURI);
params->SetIsPrivate(isPrivate);
TabParent::AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
browserDOMWin->OpenURIInFrame(nullptr, params,
openLocation,
nsIBrowserDOMWindow::OPEN_NEW,
getter_AddRefs(frameLoaderOwner));
if (!frameLoaderOwner) {
*aWindowIsNew = false;
}
newTab->SwapFrameScriptsFrom(*aFrameScripts);
return true;
}
// WindowWatcher is going to expect a valid URI to open a window
// to. If it can't find one, it's going to attempt to figure one
// out on its own, which is problematic because it can't access
// the document for the remote browser we're opening. Luckily,
// TabChild has sent us a baseURI with which we can ensure that
// the URI we pass to WindowWatcher is valid.
nsCOMPtr<nsIURI> baseURI;
*aResult = NS_NewURI(getter_AddRefs(baseURI), aBaseURI);
if (NS_WARN_IF(NS_FAILED(*aResult))) {
return true;
}
nsAutoCString finalURIString;
if (!aURI.IsEmpty()) {
nsCOMPtr<nsIURI> finalURI;
*aResult = NS_NewURI(getter_AddRefs(finalURI), NS_ConvertUTF16toUTF8(aURI).get(), baseURI);
if (NS_WARN_IF(NS_FAILED(*aResult))) {
return true;
}
finalURI->GetSpec(finalURIString);
}
nsCOMPtr<nsIDOMWindow> window;
TabParent::AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
const char* features = aFeatures.Length() ? aFeatures.get() : nullptr;
*aResult = pwwatch->OpenWindow2(parent, finalURIString.get(),
NS_ConvertUTF16toUTF8(aName).get(),
features, aCalledFromJS,
false, false, thisTabParent, nullptr, getter_AddRefs(window));
if (NS_WARN_IF(NS_FAILED(*aResult))) {
return true;
}
*aResult = NS_ERROR_FAILURE;
nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(window);
if (NS_WARN_IF(!pwindow)) {
return true;
}
nsCOMPtr<nsIDocShell> windowDocShell = pwindow->GetDocShell();
if (NS_WARN_IF(!windowDocShell)) {
return true;
}
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
windowDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
nsCOMPtr<nsIXULWindow> xulWin = do_GetInterface(treeOwner);
if (NS_WARN_IF(!xulWin)) {
return true;
}
nsCOMPtr<nsIXULBrowserWindow> xulBrowserWin;
xulWin->GetXULBrowserWindow(getter_AddRefs(xulBrowserWin));
if (NS_WARN_IF(!xulBrowserWin)) {
return true;
}
nsCOMPtr<nsITabParent> newRemoteTab;
*aResult = xulBrowserWin->ForceInitialBrowserRemote(getter_AddRefs(newRemoteTab));
if (NS_WARN_IF(NS_FAILED(*aResult))) {
return true;
}
MOZ_ASSERT(TabParent::GetFrom(newRemoteTab) == newTab);
newTab->SwapFrameScriptsFrom(*aFrameScripts);
return true;
}
/* static */ bool /* static */ bool
ContentParent::PermissionManagerAddref(const ContentParentId& aCpId, ContentParent::PermissionManagerAddref(const ContentParentId& aCpId,
const TabId& aTabId) const TabId& aTabId)

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

@ -434,6 +434,21 @@ public:
void SetNuwaParent(NuwaParent* aNuwaParent) { mNuwaParent = aNuwaParent; } void SetNuwaParent(NuwaParent* aNuwaParent) { mNuwaParent = aNuwaParent; }
void ForkNewProcess(bool aBlocking); void ForkNewProcess(bool aBlocking);
virtual bool RecvCreateWindow(PBrowserParent* aThisTabParent,
PBrowserParent* aOpener,
const uint32_t& aChromeFlags,
const bool& aCalledFromJS,
const bool& aPositionSpecified,
const bool& aSizeSpecified,
const nsString& aURI,
const nsString& aName,
const nsCString& aFeatures,
const nsString& aBaseURI,
nsresult* aResult,
bool* aWindowIsNew,
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
nsCString* aURLToLoad) override;
protected: protected:
void OnChannelConnected(int32_t pid) override; void OnChannelConnected(int32_t pid) override;
virtual void ActorDestroy(ActorDestroyReason why) override; virtual void ActorDestroy(ActorDestroyReason why) override;

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

@ -94,12 +94,6 @@ struct ShowInfo
double defaultScale; double defaultScale;
}; };
struct FrameScriptInfo
{
nsString url;
bool runInGlobalScope;
};
prio(normal upto urgent) sync protocol PBrowser prio(normal upto urgent) sync protocol PBrowser
{ {
manager PContent or PContentBridge; manager PContent or PContentBridge;
@ -165,20 +159,6 @@ parent:
Event(RemoteDOMEvent aEvent); Event(RemoteDOMEvent aEvent);
sync CreateWindow(PBrowser aNewTab,
uint32_t aChromeFlags,
bool aCalledFromJS,
bool aPositionSpecified,
bool aSizeSpecified,
nsString aURI,
nsString aName,
nsCString aFeatures,
nsString aBaseURI)
returns (nsresult rv,
bool windowOpened,
FrameScriptInfo[] frameScripts,
nsCString urlToLoad);
sync SyncMessage(nsString aMessage, ClonedMessageData aData, sync SyncMessage(nsString aMessage, ClonedMessageData aData,
CpowEntry[] aCpows, Principal aPrincipal) CpowEntry[] aCpows, Principal aPrincipal)
returns (StructuredCloneData[] retval); returns (StructuredCloneData[] retval);

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

@ -410,6 +410,12 @@ union GamepadChangeEvent {
GamepadButtonInformation; GamepadButtonInformation;
}; };
struct FrameScriptInfo
{
nsString url;
bool runInGlobalScope;
};
prio(normal upto urgent) sync protocol PContent prio(normal upto urgent) sync protocol PContent
{ {
parent spawns PPluginModule; parent spawns PPluginModule;
@ -1112,6 +1118,21 @@ parent:
sync GetGraphicsDeviceInitData() sync GetGraphicsDeviceInitData()
returns (DeviceInitData aData); returns (DeviceInitData aData);
sync CreateWindow(PBrowser aThisTab,
PBrowser aNewTab,
uint32_t aChromeFlags,
bool aCalledFromJS,
bool aPositionSpecified,
bool aSizeSpecified,
nsString aURI,
nsString aName,
nsCString aFeatures,
nsString aBaseURI)
returns (nsresult rv,
bool windowOpened,
FrameScriptInfo[] frameScripts,
nsCString urlToLoad);
sync GetDeviceStorageLocation(nsString type) sync GetDeviceStorageLocation(nsString type)
returns (nsString path); returns (nsString path);

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

@ -1115,145 +1115,19 @@ TabChild::ProvideWindow(nsIDOMWindow* aParent, uint32_t aChromeFlags,
// Note that ProvideWindowCommon may return NS_ERROR_ABORT if the // Note that ProvideWindowCommon may return NS_ERROR_ABORT if the
// open window call was canceled. It's important that we pass this error // open window call was canceled. It's important that we pass this error
// code back to our caller. // code back to our caller.
return ProvideWindowCommon(aParent, ContentChild* cc = ContentChild::GetSingleton();
iframeMoz, return cc->ProvideWindowCommon(this,
aChromeFlags, aParent,
aCalledFromJS, iframeMoz,
aPositionSpecified, aChromeFlags,
aSizeSpecified, aCalledFromJS,
aURI, aPositionSpecified,
aName, aSizeSpecified,
aFeatures, aURI,
aWindowIsNew, aName,
aReturn); aFeatures,
} aWindowIsNew,
aReturn);
nsresult
TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener,
bool aIframeMoz,
uint32_t aChromeFlags,
bool aCalledFromJS,
bool aPositionSpecified,
bool aSizeSpecified,
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool* aWindowIsNew,
nsIDOMWindow** aReturn)
{
*aReturn = nullptr;
ContentChild* cc = ContentChild::GetSingleton();
const TabId openerTabId = GetTabId();
// 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.opener() = openerTabId;
context.isBrowserElement() = IsBrowserElement();
IPCTabContext ipcContext(context);
TabId tabId;
cc->SendAllocateTabId(openerTabId,
ipcContext,
cc->GetID(),
&tabId);
RefPtr<TabChild> newChild = new TabChild(ContentChild::GetSingleton(), tabId,
/* TabContext */ *this, aChromeFlags);
if (NS_FAILED(newChild->Init())) {
return NS_ERROR_ABORT;
}
context.opener() = this;
unused << Manager()->SendPBrowserConstructor(
// We release this ref in DeallocPBrowserChild
RefPtr<TabChild>(newChild).forget().take(),
tabId, IPCTabContext(context), aChromeFlags,
cc->GetID(), cc->IsForApp(), cc->IsForBrowser());
nsAutoCString spec;
if (aURI) {
aURI->GetSpec(spec);
}
NS_ConvertUTF8toUTF16 url(spec);
nsString name(aName);
nsAutoCString features(aFeatures);
nsTArray<FrameScriptInfo> frameScripts;
nsCString urlToLoad;
if (aIframeMoz) {
newChild->SendBrowserFrameOpenWindow(this, url, name,
NS_ConvertUTF8toUTF16(features),
aWindowIsNew);
} else {
nsCOMPtr<nsPIDOMWindow> opener = do_QueryInterface(aOpener);
nsCOMPtr<nsIDocument> doc = opener->GetDoc();
nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
if (!baseURI) {
NS_ERROR("nsIDocument didn't return a base URI");
return NS_ERROR_FAILURE;
}
nsAutoCString baseURIString;
baseURI->GetSpec(baseURIString);
nsresult rv;
if (!SendCreateWindow(newChild,
aChromeFlags, aCalledFromJS, aPositionSpecified,
aSizeSpecified, url,
name, features,
NS_ConvertUTF8toUTF16(baseURIString),
&rv,
aWindowIsNew,
&frameScripts,
&urlToLoad)) {
return NS_ERROR_NOT_AVAILABLE;
}
if (NS_FAILED(rv)) {
return rv;
}
}
if (!*aWindowIsNew) {
PBrowserChild::Send__delete__(newChild);
return NS_ERROR_ABORT;
}
TextureFactoryIdentifier textureFactoryIdentifier;
uint64_t layersId = 0;
PRenderFrameChild* renderFrame = newChild->SendPRenderFrameConstructor();
newChild->SendGetRenderFrameInfo(renderFrame,
&textureFactoryIdentifier,
&layersId);
if (layersId == 0) { // if renderFrame is invalid.
PRenderFrameChild::Send__delete__(renderFrame);
renderFrame = nullptr;
}
// Unfortunately we don't get a window unless we've shown the frame. That's
// pretty bogus; see bug 763602.
newChild->DoFakeShow(textureFactoryIdentifier, layersId, renderFrame);
for (size_t i = 0; i < frameScripts.Length(); i++) {
FrameScriptInfo& info = frameScripts[i];
if (!newChild->RecvLoadRemoteScript(info.url(), info.runInGlobalScope())) {
MOZ_CRASH();
}
}
if (!urlToLoad.IsEmpty()) {
newChild->RecvLoadURL(urlToLoad, BrowserConfiguration());
}
nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation());
win.forget(aReturn);
return NS_OK;
} }
void void

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

@ -240,6 +240,16 @@ public:
static already_AddRefed<TabChild> FindTabChild(const TabId& aTabId); static already_AddRefed<TabChild> FindTabChild(const TabId& aTabId);
public: public:
/**
* Create a new TabChild object.
*/
TabChild(nsIContentChild* aManager,
const TabId& aTabId,
const TabContext& aContext,
uint32_t aChromeFlags);
nsresult Init();
/** /**
* This is expected to be called off the critical path to content * This is expected to be called off the critical path to content
* startup. This is an opportunity to load things that are slow * startup. This is an opportunity to load things that are slow
@ -510,6 +520,11 @@ public:
virtual ScreenIntSize GetInnerSize() override; virtual ScreenIntSize GetInnerSize() override;
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
void DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
const uint64_t& aLayersId,
PRenderFrameChild* aRenderFrame);
protected: protected:
virtual ~TabChild(); virtual ~TabChild();
@ -535,16 +550,6 @@ protected:
#endif #endif
private: private:
/**
* Create a new TabChild object.
*/
TabChild(nsIContentChild* aManager,
const TabId& aTabId,
const TabContext& aContext,
uint32_t aChromeFlags);
nsresult Init();
class DelayedFireContextMenuEvent; class DelayedFireContextMenuEvent;
// Notify others that our TabContext has been updated. (At the moment, this // Notify others that our TabContext has been updated. (At the moment, this
@ -564,11 +569,6 @@ private:
void DestroyWindow(); void DestroyWindow();
void SetProcessNameToAppName(); void SetProcessNameToAppName();
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
void DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
const uint64_t& aLayersId,
PRenderFrameChild* aRenderFrame);
void ApplyShowInfo(const ShowInfo& aInfo); void ApplyShowInfo(const ShowInfo& aInfo);
// These methods are used for tracking synthetic mouse events // These methods are used for tracking synthetic mouse events
@ -581,19 +581,6 @@ private:
void CancelTapTracking(); void CancelTapTracking();
void UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus); void UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus);
nsresult
ProvideWindowCommon(nsIDOMWindow* aOpener,
bool aIframeMoz,
uint32_t aChromeFlags,
bool aCalledFromJS,
bool aPositionSpecified,
bool aSizeSpecified,
nsIURI* aURI,
const nsAString& aName,
const nsACString& aFeatures,
bool* aWindowIsNew,
nsIDOMWindow** aReturn);
bool HasValidInnerSize(); bool HasValidInnerSize();
void SetTabId(const TabId& aTabId); void SetTabId(const TabId& aTabId);

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

@ -50,7 +50,6 @@
#include "nsIContent.h" #include "nsIContent.h"
#include "nsIDocShell.h" #include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h" #include "nsIDocShellTreeOwner.h"
#include "nsIDOMChromeWindow.h"
#include "nsIDOMElement.h" #include "nsIDOMElement.h"
#include "nsIDOMEvent.h" #include "nsIDOMEvent.h"
#include "nsIDOMWindow.h" #include "nsIDOMWindow.h"
@ -61,26 +60,20 @@
#include "nsIPromptFactory.h" #include "nsIPromptFactory.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsIWebBrowserChrome.h" #include "nsIWebBrowserChrome.h"
#include "nsIWindowCreator2.h"
#include "nsIXULBrowserWindow.h" #include "nsIXULBrowserWindow.h"
#include "nsIXULWindow.h" #include "nsIXULWindow.h"
#include "nsIRemoteBrowser.h" #include "nsIRemoteBrowser.h"
#include "nsViewManager.h" #include "nsViewManager.h"
#include "nsVariant.h" #include "nsVariant.h"
#include "nsIWidget.h" #include "nsIWidget.h"
#include "nsIWindowMediator.h"
#include "nsIWindowWatcher.h"
#ifndef XP_WIN #ifndef XP_WIN
#include "nsJARProtocolHandler.h" #include "nsJARProtocolHandler.h"
#endif #endif
#include "nsOpenURIInFrameParams.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "nsPIWindowWatcher.h"
#include "nsPresShell.h" #include "nsPresShell.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsWindowWatcher.h"
#include "private/pprio.h" #include "private/pprio.h"
#include "PermissionMessageUtils.h" #include "PermissionMessageUtils.h"
#include "StructuredCloneData.h" #include "StructuredCloneData.h"
@ -723,249 +716,6 @@ TabParent::RecvEvent(const RemoteDOMEvent& aEvent)
return true; return true;
} }
struct MOZ_STACK_CLASS TabParent::AutoUseNewTab final
{
public:
AutoUseNewTab(TabParent* aNewTab, bool* aWindowIsNew, nsCString* aURLToLoad)
: mNewTab(aNewTab), mWindowIsNew(aWindowIsNew), mURLToLoad(aURLToLoad)
{
MOZ_ASSERT(!TabParent::sNextTabParent);
MOZ_ASSERT(!aNewTab->mCreatingWindow);
TabParent::sNextTabParent = aNewTab;
aNewTab->mCreatingWindow = true;
aNewTab->mDelayedURL.Truncate();
}
~AutoUseNewTab()
{
mNewTab->mCreatingWindow = false;
*mURLToLoad = mNewTab->mDelayedURL;
if (TabParent::sNextTabParent) {
MOZ_ASSERT(TabParent::sNextTabParent == mNewTab);
TabParent::sNextTabParent = nullptr;
*mWindowIsNew = false;
}
}
private:
TabParent* mNewTab;
bool* mWindowIsNew;
nsCString* mURLToLoad;
};
static already_AddRefed<nsPIDOMWindow>
FindMostRecentOpenWindow()
{
nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
windowMediator->GetEnumerator(MOZ_UTF16("navigator:browser"),
getter_AddRefs(windowEnumerator));
nsCOMPtr<nsPIDOMWindow> latest;
bool hasMore = false;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(windowEnumerator->HasMoreElements(&hasMore)));
while (hasMore) {
nsCOMPtr<nsISupports> item;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(windowEnumerator->GetNext(getter_AddRefs(item))));
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(item);
if (window && !window->Closed()) {
latest = window;
}
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(windowEnumerator->HasMoreElements(&hasMore)));
}
return latest.forget();
}
bool
TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
const uint32_t& aChromeFlags,
const bool& aCalledFromJS,
const bool& aPositionSpecified,
const bool& aSizeSpecified,
const nsString& aURI,
const nsString& aName,
const nsCString& aFeatures,
const nsString& aBaseURI,
nsresult* aResult,
bool* aWindowIsNew,
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
nsCString* aURLToLoad)
{
// We always expect to open a new window here. If we don't, it's an error.
*aWindowIsNew = true;
// The content process should never be in charge of computing whether or
// not a window should be private or remote - the parent will do that.
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW));
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW));
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME));
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW));
if (NS_WARN_IF(IsBrowserOrApp()))
return false;
nsCOMPtr<nsPIWindowWatcher> pwwatch =
do_GetService(NS_WINDOWWATCHER_CONTRACTID, aResult);
if (NS_WARN_IF(NS_FAILED(*aResult)))
return true;
TabParent* newTab = TabParent::GetFrom(aNewTab);
MOZ_ASSERT(newTab);
// Content has requested that we open this new content window, so
// we must have an opener.
newTab->SetHasContentOpener(true);
nsCOMPtr<nsIContent> frame(do_QueryInterface(mFrameElement));
nsCOMPtr<nsPIDOMWindow> parent;
if (frame) {
parent = frame->OwnerDoc()->GetWindow();
// If our chrome window is in the process of closing, don't try to open a
// new tab in it.
if (parent && parent->Closed()) {
parent = nullptr;
}
}
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin = mBrowserDOMWindow;
// If we haven't found a chrome window to open in, just use the most recently
// opened one.
if (!parent) {
parent = FindMostRecentOpenWindow();
if (NS_WARN_IF(!parent)) {
*aResult = NS_ERROR_FAILURE;
return true;
}
nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(parent);
if (rootChromeWin) {
rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
}
}
int32_t openLocation =
nsWindowWatcher::GetWindowOpenLocation(parent, aChromeFlags, aCalledFromJS,
aPositionSpecified, aSizeSpecified);
MOZ_ASSERT(openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB ||
openLocation == nsIBrowserDOMWindow::OPEN_NEWWINDOW);
// Opening new tabs is the easy case...
if (openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB) {
if (NS_WARN_IF(!browserDOMWin)) {
*aResult = NS_ERROR_FAILURE;
return true;
}
bool isPrivate;
nsCOMPtr<nsILoadContext> loadContext = GetLoadContext();
loadContext->GetUsePrivateBrowsing(&isPrivate);
nsCOMPtr<nsIOpenURIInFrameParams> params = new nsOpenURIInFrameParams();
params->SetReferrer(aBaseURI);
params->SetIsPrivate(isPrivate);
AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
browserDOMWin->OpenURIInFrame(nullptr, params,
openLocation,
nsIBrowserDOMWindow::OPEN_NEW,
getter_AddRefs(frameLoaderOwner));
if (!frameLoaderOwner) {
*aWindowIsNew = false;
}
aFrameScripts->SwapElements(newTab->mDelayedFrameScripts);
return true;
}
// WindowWatcher is going to expect a valid URI to open a window
// to. If it can't find one, it's going to attempt to figure one
// out on its own, which is problematic because it can't access
// the document for the remote browser we're opening. Luckily,
// TabChild has sent us a baseURI with which we can ensure that
// the URI we pass to WindowWatcher is valid.
nsCOMPtr<nsIURI> baseURI;
*aResult = NS_NewURI(getter_AddRefs(baseURI), aBaseURI);
if (NS_WARN_IF(NS_FAILED(*aResult)))
return true;
nsAutoCString finalURIString;
if (!aURI.IsEmpty()) {
nsCOMPtr<nsIURI> finalURI;
*aResult = NS_NewURI(getter_AddRefs(finalURI), NS_ConvertUTF16toUTF8(aURI).get(), baseURI);
if (NS_WARN_IF(NS_FAILED(*aResult)))
return true;
finalURI->GetSpec(finalURIString);
}
nsCOMPtr<nsIDOMWindow> window;
AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
const char* features = aFeatures.Length() ? aFeatures.get() : nullptr;
*aResult = pwwatch->OpenWindow2(parent, finalURIString.get(),
NS_ConvertUTF16toUTF8(aName).get(),
features, aCalledFromJS,
false, false, this, nullptr, getter_AddRefs(window));
if (NS_WARN_IF(NS_FAILED(*aResult)))
return true;
*aResult = NS_ERROR_FAILURE;
nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(window);
if (NS_WARN_IF(!pwindow)) {
return true;
}
nsCOMPtr<nsIDocShell> windowDocShell = pwindow->GetDocShell();
if (NS_WARN_IF(!windowDocShell)) {
return true;
}
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
windowDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
nsCOMPtr<nsIXULWindow> xulWin = do_GetInterface(treeOwner);
if (NS_WARN_IF(!xulWin)) {
return true;
}
nsCOMPtr<nsIXULBrowserWindow> xulBrowserWin;
xulWin->GetXULBrowserWindow(getter_AddRefs(xulBrowserWin));
if (NS_WARN_IF(!xulBrowserWin)) {
return true;
}
nsCOMPtr<nsITabParent> newRemoteTab;
*aResult = xulBrowserWin->ForceInitialBrowserRemote(getter_AddRefs(newRemoteTab));
if (NS_WARN_IF(NS_FAILED(*aResult)))
return true;
MOZ_ASSERT(TabParent::GetFrom(newRemoteTab) == newTab);
aFrameScripts->SwapElements(newTab->mDelayedFrameScripts);
return true;
}
TabParent* TabParent::sNextTabParent; TabParent* TabParent::sNextTabParent;
/* static */ TabParent* /* static */ TabParent*

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

@ -11,6 +11,7 @@
#include "mozilla/ContentCache.h" #include "mozilla/ContentCache.h"
#include "mozilla/dom/ipc/IdType.h" #include "mozilla/dom/ipc/IdType.h"
#include "mozilla/dom/PBrowserParent.h" #include "mozilla/dom/PBrowserParent.h"
#include "mozilla/dom/PContent.h"
#include "mozilla/dom/PFilePickerParent.h" #include "mozilla/dom/PFilePickerParent.h"
#include "mozilla/dom/TabContext.h" #include "mozilla/dom/TabContext.h"
#include "mozilla/EventForwards.h" #include "mozilla/EventForwards.h"
@ -93,6 +94,9 @@ class TabParent final : public PBrowserParent
virtual ~TabParent(); virtual ~TabParent();
public: public:
// Helper class for ContentParent::RecvCreateWindow.
struct AutoUseNewTab;
// nsITabParent // nsITabParent
NS_DECL_NSITABPARENT NS_DECL_NSITABPARENT
// nsIDOMEventListener interfaces // nsIDOMEventListener interfaces
@ -125,6 +129,12 @@ public:
mBrowserDOMWindow = aBrowserDOMWindow; mBrowserDOMWindow = aBrowserDOMWindow;
} }
void SetHasContentOpener(bool aHasContentOpener);
void SwapFrameScriptsFrom(nsTArray<FrameScriptInfo>& aFrameScripts) {
aFrameScripts.SwapElements(mDelayedFrameScripts);
}
already_AddRefed<nsILoadContext> GetLoadContext(); already_AddRefed<nsILoadContext> GetLoadContext();
already_AddRefed<nsIWidget> GetTopLevelWidget(); already_AddRefed<nsIWidget> GetTopLevelWidget();
nsIXULBrowserWindow* GetXULBrowserWindow(); nsIXULBrowserWindow* GetXULBrowserWindow();
@ -147,19 +157,6 @@ public:
const nsString& aName, const nsString& aName,
const nsString& aFeatures, const nsString& aFeatures,
bool* aOutWindowOpened) override; bool* aOutWindowOpened) override;
virtual bool RecvCreateWindow(PBrowserParent* aOpener,
const uint32_t& aChromeFlags,
const bool& aCalledFromJS,
const bool& aPositionSpecified,
const bool& aSizeSpecified,
const nsString& aURI,
const nsString& aName,
const nsCString& aFeatures,
const nsString& aBaseURI,
nsresult* aResult,
bool* aWindowIsNew,
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
nsCString* aURLToLoad) override;
virtual bool RecvSyncMessage(const nsString& aMessage, virtual bool RecvSyncMessage(const nsString& aMessage,
const ClonedMessageData& aData, const ClonedMessageData& aData,
InfallibleTArray<CpowEntry>&& aCpows, InfallibleTArray<CpowEntry>&& aCpows,
@ -497,8 +494,6 @@ protected:
bool InitBrowserConfiguration(const nsCString& aURI, bool InitBrowserConfiguration(const nsCString& aURI,
BrowserConfiguration& aConfiguration); BrowserConfiguration& aConfiguration);
void SetHasContentOpener(bool aHasContentOpener);
// Decide whether we have to use a new process to reload the URI associated // Decide whether we have to use a new process to reload the URI associated
// with the given channel. // with the given channel.
bool ShouldSwitchProcess(nsIChannel* aChannel); bool ShouldSwitchProcess(nsIChannel* aChannel);
@ -584,9 +579,6 @@ private:
TabId mTabId; TabId mTabId;
// Helper class for RecvCreateWindow.
struct AutoUseNewTab;
// When loading a new tab or window via window.open, the child process sends // When loading a new tab or window via window.open, the child process sends
// a new PBrowser to use. We store that tab in sNextTabParent and then // a new PBrowser to use. We store that tab in sNextTabParent and then
// proceed through the browser's normal paths to create a new // proceed through the browser's normal paths to create a new
@ -655,6 +647,38 @@ public:
static TabParent* GetTabParentFromLayersId(uint64_t aLayersId); static TabParent* GetTabParentFromLayersId(uint64_t aLayersId);
}; };
struct MOZ_STACK_CLASS TabParent::AutoUseNewTab final
{
public:
AutoUseNewTab(TabParent* aNewTab, bool* aWindowIsNew, nsCString* aURLToLoad)
: mNewTab(aNewTab), mWindowIsNew(aWindowIsNew), mURLToLoad(aURLToLoad)
{
MOZ_ASSERT(!TabParent::sNextTabParent);
MOZ_ASSERT(!aNewTab->mCreatingWindow);
TabParent::sNextTabParent = aNewTab;
aNewTab->mCreatingWindow = true;
aNewTab->mDelayedURL.Truncate();
}
~AutoUseNewTab()
{
mNewTab->mCreatingWindow = false;
*mURLToLoad = mNewTab->mDelayedURL;
if (TabParent::sNextTabParent) {
MOZ_ASSERT(TabParent::sNextTabParent == mNewTab);
TabParent::sNextTabParent = nullptr;
*mWindowIsNew = false;
}
}
private:
TabParent* mNewTab;
bool* mWindowIsNew;
nsCString* mURLToLoad;
};
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla