diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index 4d7e9490782b..8683b4f314d8 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -183,6 +183,8 @@ FORCE_STATIC_LIB = 1 EXTRA_COMPONENTS = $(srcdir)/nsBadCertHandler.js +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk INCLUDES += \ @@ -198,6 +200,7 @@ INCLUDES += \ -I$(srcdir)/../../../dom/base \ -I$(srcdir)/../../xml/document/src \ -I$(topsrcdir)/xpcom/io \ + -I$(topsrcdir)/dom/ipc \ $(NULL) DEFINES += -D_IMPL_NS_LAYOUT diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index 7bf0b16ea448..d29c4f0dece8 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -83,6 +83,17 @@ #include "nsINameSpaceManager.h" #include "nsThreadUtils.h" +#include "nsIView.h" + +#include "TabParent.h" + +#include "mozcontainer.h" + +#include +#include + +using namespace mozilla; +using namespace mozilla::tabs; class nsAsyncDocShellDestroyer : public nsRunnable { @@ -193,6 +204,18 @@ nsresult nsFrameLoader::ReallyStartLoading() { NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInDoc()); + + if (!mTriedNewProcess) { + TryNewProcess(); + mTriedNewProcess = PR_TRUE; + } + + if (mChildProcess) { + // FIXME get error codes from child + mChildProcess->LoadURL(mURIToLoad); + return NS_OK; + } + // Just to be safe, recheck uri. nsresult rv = CheckURILoad(mURIToLoad); NS_ENSURE_SUCCESS(rv, rv); @@ -1007,3 +1030,103 @@ nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI) return NS_OK; } + +PRBool +nsFrameLoader::TryNewProcess() +{ + nsIDocument* doc = mOwnerContent->GetDocument(); + if (!doc) { + return NS_ERROR_UNEXPECTED; + } + + if (doc->GetDisplayDocument()) { + // Don't allow subframe loads in external reference documents + return NS_ERROR_NOT_AVAILABLE; + } + + nsCOMPtr parentAsWebNav = + do_GetInterface(doc->GetScriptGlobalObject()); + + if (!parentAsWebNav) { + return PR_FALSE; + } + + nsCOMPtr parentAsItem(do_QueryInterface(parentAsWebNav)); + + PRInt32 parentType; + parentAsItem->GetItemType(&parentType); + + if (parentType != nsIDocShellTreeItem::typeChrome) { + return PR_FALSE; + } + + if (!mOwnerContent->IsNodeOfType(nsINode::eXUL)) { + return PR_FALSE; + } + + NS_ERROR("trying to start new process"); + nsAutoString value; + mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value); + + if (!value.LowerCaseEqualsLiteral("content") && + !StringBeginsWith(value, NS_LITERAL_STRING("content-"), + nsCaseInsensitiveStringComparator())) { + return PR_FALSE; + } + + // FIXME shouldn't need to launch a new process every time get here + + // XXXnasty hack get our (parent) widget + doc->FlushPendingNotifications(Flush_Layout); + nsIFrame* ourFrame = + doc->GetPrimaryShell()->GetPrimaryFrameFor(mOwnerContent); + nsIView* ancestorView = ourFrame->GetView(); + + nsIView* firstChild = ancestorView->GetFirstChild(); + if (!firstChild) { + NS_ERROR("no first child"); + return PR_FALSE; + } + + nsIWidget* w = firstChild->GetWidget(); + if (!w) { + NS_ERROR("we're stuffed!"); + return PR_FALSE; + } + // FIXME check that this widget has the size and position we expect for + // this iframe? + + GdkWindow* parent_win = + static_cast(w->GetNativeData(NS_NATIVE_WINDOW)); + + gpointer user_data = nsnull; + gdk_window_get_user_data(parent_win, &user_data); + + MozContainer* parentMozContainer = MOZ_CONTAINER(user_data); + GtkContainer* container = GTK_CONTAINER(parentMozContainer); + + // create the widget for the child and add it to the parent's window + GtkWidget* socket = gtk_socket_new(); + gtk_widget_set_parent_window(socket, parent_win); + gtk_container_add(container, socket); + gtk_widget_realize(socket); + + // set the child window's size and position + nsPresContext* presContext = ourFrame->PresContext(); + GtkAllocation alloc; + alloc.x = 0; // setting position doesn't look necessary + alloc.y = 0; + alloc.width = presContext->AppUnitsToDevPixels(ourFrame->GetSize().width); + alloc.height = presContext->AppUnitsToDevPixels(ourFrame->GetSize().height); + gtk_widget_size_allocate(socket, &alloc); + + gtk_widget_show(socket); + + GdkNativeWindow id = gtk_socket_get_id((GtkSocket*)socket); + + mChildProcess = new TabParent(id); + + mChildProcess->Move(0, 0, alloc.width, alloc.height); + + return PR_TRUE; +} diff --git a/content/base/src/nsFrameLoader.h b/content/base/src/nsFrameLoader.h index 21ed338b520b..6c50e43dabe3 100644 --- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -48,9 +48,15 @@ #include "nsStringFwd.h" #include "nsIFrameLoader.h" #include "nsIURI.h" +#include "nsAutoPtr.h" class nsIContent; class nsIURI; +namespace mozilla { + namespace tabs { + class TabParent; + } +} class nsFrameLoader : public nsIFrameLoader { @@ -61,7 +67,9 @@ public: mIsTopLevelContent(PR_FALSE), mDestroyCalled(PR_FALSE), mNeedsAsyncDestroy(PR_FALSE), - mInSwap(PR_FALSE) + mInSwap(PR_FALSE), + mChildProcess(nsnull), + mTriedNewProcess(PR_FALSE) {} ~nsFrameLoader() { @@ -89,6 +97,9 @@ private: NS_HIDDEN_(void) GetURL(nsString& aURL); nsresult CheckURILoad(nsIURI* aURI); + // True means new process started; nothing else to do + PRBool TryNewProcess(); + nsCOMPtr mDocShell; nsCOMPtr mURIToLoad; nsIContent *mOwnerContent; // WEAK @@ -97,6 +108,10 @@ private: PRPackedBool mDestroyCalled : 1; PRPackedBool mNeedsAsyncDestroy : 1; PRPackedBool mInSwap : 1; + + // XXX leaking + mozilla::tabs::TabParent* mChildProcess; + PRBool mTriedNewProcess; }; #endif diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index e7050db5a053..35aa902ddf73 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -9845,10 +9845,13 @@ nsDocShell::EnsureScriptEnvironment() NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE); nsCOMPtr browserChrome(do_GetInterface(mTreeOwner)); - NS_ENSURE_TRUE(browserChrome, NS_ERROR_NOT_AVAILABLE); PRUint32 chromeFlags; - browserChrome->GetChromeFlags(&chromeFlags); + if (browserChrome) { + browserChrome->GetChromeFlags(&chromeFlags); + } else { + chromeFlags = 0; + } PRBool isModalContentWindow = (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL) && diff --git a/dom/Makefile.in b/dom/Makefile.in index 150891025d33..4fe7fb736bbb 100644 --- a/dom/Makefile.in +++ b/dom/Makefile.in @@ -84,6 +84,7 @@ DIRS += \ ifdef MOZ_IPC DIRS += \ plugins \ + ipc \ $(NULL) endif diff --git a/dom/ipc/IFrameEmbedding.ipdl b/dom/ipc/IFrameEmbedding.ipdl new file mode 100644 index 000000000000..5e347cec0531 --- /dev/null +++ b/dom/ipc/IFrameEmbedding.ipdl @@ -0,0 +1,13 @@ +using MagicWindowHandle; + +rpc protocol IFrameEmbedding +{ + rpc out init(MagicWindowHandle parentWidget); + + rpc out loadURL(String uri); + + rpc out move(uint32_t x, + uint32_t y, + uint32_t width, + uint32_t height); +}; diff --git a/dom/ipc/IFrameEmbeddingProtocol.h b/dom/ipc/IFrameEmbeddingProtocol.h new file mode 100644 index 000000000000..e618b810dad3 --- /dev/null +++ b/dom/ipc/IFrameEmbeddingProtocol.h @@ -0,0 +1,150 @@ +// +// Automatically generated by ipdlc. +// Edit at your own risk. +// +#ifndef IFrameEmbeddingProtocol_h +#define IFrameEmbeddingProtocol_h +#include "nscore.h" +#include "IPC/IPCMessageUtils.h" +#include "mozilla/ipc/MessageTypes.h" + +typedef mozilla::ipc::String String; +typedef mozilla::ipc::StringArray StringArray; +class NS_FINAL_CLASS IFrameEmbeddingProtocol +{ +public: + /*interface*/ class Parent + { + public: + protected: + Parent() { } + virtual ~Parent() { } + Parent(const Parent&); + Parent& operator=(const Parent&); + }; + + /*interface*/ class Child + { + public: + virtual nsresult init( + const MagicWindowHandle& parentWidget) = 0; + virtual nsresult loadURL( + const String& uri) = 0; + virtual nsresult move( + const uint32_t& x, const uint32_t& y, const uint32_t& width, const uint32_t& height) = 0; + protected: + Child() { } + virtual ~Child() { } + Child(const Child&); + Child& operator=(const Child&); + }; + + enum State { }; +private: + IFrameEmbeddingProtocol(); + virtual ~IFrameEmbeddingProtocol() = 0; +}; + +// Parent->child messages + +enum IFrameEmbedding_ParentToChildMsgType { + IFrameEmbedding_ParentToChildStart = IFrameEmbedding_ParentToChildMsgStart << 12, + IFrameEmbedding_ParentToChildPreStart = (IFrameEmbedding_ParentToChildMsgStart << 12) - 1, + + IFrameEmbedding_ParentToChildMsg_init__ID, + IFrameEmbedding_ParentToChildMsg_loadURL__ID, + IFrameEmbedding_ParentToChildMsg_move__ID, + + + IFrameEmbedding_ParentToChildEnd +}; + +class IFrameEmbedding_ParentToChildMsg_init : + public IPC::MessageWithTuple +{ +public: + enum { ID = IFrameEmbedding_ParentToChildMsg_init__ID }; + IFrameEmbedding_ParentToChildMsg_init( + const MagicWindowHandle& parentWidget) : + IPC::MessageWithTuple( + MSG_ROUTING_CONTROL, ID, + parentWidget) + { } +}; + +class IFrameEmbedding_ParentToChildMsg_loadURL : + public IPC::MessageWithTuple +{ +public: + enum { ID = IFrameEmbedding_ParentToChildMsg_loadURL__ID }; + IFrameEmbedding_ParentToChildMsg_loadURL( + const String& uri) : + IPC::MessageWithTuple( + MSG_ROUTING_CONTROL, ID, + uri) + { } +}; + +class IFrameEmbedding_ParentToChildMsg_move : + public IPC::MessageWithTuple< Tuple4 < + uint32_t, uint32_t, uint32_t, uint32_t> > +{ +public: + enum { ID = IFrameEmbedding_ParentToChildMsg_move__ID }; + IFrameEmbedding_ParentToChildMsg_move( + const uint32_t& x, const uint32_t& y, const uint32_t& width, const uint32_t& height) : + IPC::MessageWithTuple< Tuple4 < + uint32_t, uint32_t, uint32_t, uint32_t> >( + MSG_ROUTING_CONTROL, ID, + MakeTuple( + x, y, width, height)) + { } +}; + + +// Child->parent messages + +enum IFrameEmbedding_ChildToParentMsgType { + IFrameEmbedding_ChildToParentStart = IFrameEmbedding_ChildToParentMsgStart << 12, + IFrameEmbedding_ChildToParentPreStart = (IFrameEmbedding_ChildToParentMsgStart << 12) - 1, + + + IFrameEmbedding_ChildToParentMsg_Reply_init__ID, + IFrameEmbedding_ChildToParentMsg_Reply_loadURL__ID, + IFrameEmbedding_ChildToParentMsg_Reply_move__ID, + + IFrameEmbedding_ChildToParentEnd +}; + +class IFrameEmbedding_ChildToParentMsg_Reply_init : + public IPC::Message +{ +public: + enum { ID = IFrameEmbedding_ChildToParentMsg_Reply_init__ID }; + IFrameEmbedding_ChildToParentMsg_Reply_init() : + IPC::Message(MSG_ROUTING_CONTROL, ID, PRIORITY_NORMAL) + { } +}; + +class IFrameEmbedding_ChildToParentMsg_Reply_loadURL : + public IPC::Message +{ +public: + enum { ID = IFrameEmbedding_ChildToParentMsg_Reply_loadURL__ID }; + IFrameEmbedding_ChildToParentMsg_Reply_loadURL() : + IPC::Message(MSG_ROUTING_CONTROL, ID, PRIORITY_NORMAL) + { } +}; + +class IFrameEmbedding_ChildToParentMsg_Reply_move : + public IPC::Message +{ +public: + enum { ID = IFrameEmbedding_ChildToParentMsg_Reply_move__ID }; + IFrameEmbedding_ChildToParentMsg_Reply_move() : + IPC::Message(MSG_ROUTING_CONTROL, ID, PRIORITY_NORMAL) + { } +}; + + +#endif // ifndef IFrameEmbeddingProtocol_h diff --git a/dom/ipc/IFrameEmbeddingProtocolChild.h b/dom/ipc/IFrameEmbeddingProtocolChild.h new file mode 100644 index 000000000000..dbcc2456dc0a --- /dev/null +++ b/dom/ipc/IFrameEmbeddingProtocolChild.h @@ -0,0 +1,88 @@ +// +// Automatically generated by ipdlc. +// Edit at your own risk. +// +#include "IFrameEmbeddingProtocol.h" + +#include "mozilla/ipc/RPCChannel.h" +using mozilla::ipc::RPCChannel; +using IPC::Message; + +class NS_FINAL_CLASS IFrameEmbeddingProtocolChild : + public IFrameEmbeddingProtocol::Parent, + public RPCChannel::Listener +{ +public: + IFrameEmbeddingProtocolChild(IFrameEmbeddingProtocol::Child* aChild) : + mChild(aChild), + mRpc(this) + { } + + bool Open(IPC::Channel* aChannel, MessageLoop* aIOLoop) + { + return mRpc.Open(aChannel, aIOLoop); + } + + void Close() + { + mRpc.Close(); + } + + virtual Result OnCallReceived(const Message& msg, Message** reply) + { + switch (msg.type()) { + case IFrameEmbedding_ParentToChildMsg_init__ID: { + MagicWindowHandle parentWidget; + MagicWindowHandle p; + IFrameEmbedding_ParentToChildMsg_init::Read(&msg, &p); + + parentWidget = p; + + nsresult _rv = mChild->init( + parentWidget); + *reply = new IFrameEmbedding_ChildToParentMsg_Reply_init(); + (*reply)->set_reply(); + return MsgProcessed; + } + case IFrameEmbedding_ParentToChildMsg_loadURL__ID: { + String uri; + String p; + IFrameEmbedding_ParentToChildMsg_loadURL::Read(&msg, &p); + + uri = p; + + nsresult _rv = mChild->loadURL( + uri); + *reply = new IFrameEmbedding_ChildToParentMsg_Reply_loadURL(); + (*reply)->set_reply(); + return MsgProcessed; + } + case IFrameEmbedding_ParentToChildMsg_move__ID: { + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; + IFrameEmbedding_ParentToChildMsg_move::Param p; + IFrameEmbedding_ParentToChildMsg_move::Read(&msg, &p); + + x = p.a; + y = p.b; + width = p.c; + height = p.d; + + nsresult _rv = mChild->move( + x, y, width, height); + *reply = new IFrameEmbedding_ChildToParentMsg_Reply_move(); + (*reply)->set_reply(); + return MsgProcessed; + } + default: { + return MsgNotKnown; + } + } + } + +private: + IFrameEmbeddingProtocol::Child* mChild; + RPCChannel mRpc; +}; diff --git a/dom/ipc/IFrameEmbeddingProtocolParent.h b/dom/ipc/IFrameEmbeddingProtocolParent.h new file mode 100644 index 000000000000..765a1c652db0 --- /dev/null +++ b/dom/ipc/IFrameEmbeddingProtocolParent.h @@ -0,0 +1,82 @@ +// +// Automatically generated by ipdlc. +// Edit at your own risk. +// +#include "IFrameEmbeddingProtocol.h" + +#include "mozilla/ipc/RPCChannel.h" +using mozilla::ipc::RPCChannel; +using IPC::Message; + +class NS_FINAL_CLASS IFrameEmbeddingProtocolParent : + public IFrameEmbeddingProtocol::Child, + public RPCChannel::Listener +{ +public: + IFrameEmbeddingProtocolParent(IFrameEmbeddingProtocol::Parent* aParent) : + mParent(aParent), + mRpc(this) + { } + + bool Open(IPC::Channel* aChannel) + { + return mRpc.Open(aChannel); + } + + void Close() + { + mRpc.Close(); + } + + virtual nsresult init( + const MagicWindowHandle& parentWidget) + { + Message reply; + nsresult _rv = mRpc.Call(new IFrameEmbedding_ParentToChildMsg_init( + parentWidget) + , &reply); + + if (NS_OK == _rv) { + } + return _rv; + } + + virtual nsresult loadURL( + const String& uri) + { + Message reply; + nsresult _rv = mRpc.Call(new IFrameEmbedding_ParentToChildMsg_loadURL( + uri) + , &reply); + + if (NS_OK == _rv) { + } + return _rv; + } + + virtual nsresult move( + const uint32_t& x, const uint32_t& y, const uint32_t& width, const uint32_t& height) + { + Message reply; + nsresult _rv = mRpc.Call(new IFrameEmbedding_ParentToChildMsg_move( + x, y, width, height) + , &reply); + + if (NS_OK == _rv) { + } + return _rv; + } + + virtual Result OnCallReceived(const Message& msg, Message** reply) + { + switch (msg.type()) { + default: { + return MsgNotKnown; + } + } + } + +private: + IFrameEmbeddingProtocol::Parent* mParent; + RPCChannel mRpc; +}; diff --git a/dom/ipc/Makefile.in b/dom/ipc/Makefile.in new file mode 100644 index 000000000000..528f30af5a9b --- /dev/null +++ b/dom/ipc/Makefile.in @@ -0,0 +1,27 @@ +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = dom +LIBRARY_NAME = domipc_s +LIBXUL_LIBRARY = 1 +FORCE_STATIC_LIB = 1 +EXPORT_LIBRARY = 1 + +CPPSRCS = \ + TabParent.cpp \ + TabProcessParent.cpp \ + TabChild.cpp \ + TabThread.cpp \ + $(NULL) + +TOOL_DIRS = app + +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk +include $(topsrcdir)/config/rules.mk + +DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"' diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp new file mode 100644 index 000000000000..8846bb6bf3d2 --- /dev/null +++ b/dom/ipc/TabChild.cpp @@ -0,0 +1,84 @@ +/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */ + +#include "TabChild.h" + +#include "nsIWebBrowser.h" +#include "nsEmbedCID.h" +#include "nsComponentManagerUtils.h" +#include "nsIBaseWindow.h" +#include "nsIDocShellTreeItem.h" +#include "nsThreadUtils.h" +#include +#include + +using namespace mozilla::tabs; + +TabChild::TabChild() + : mWidget(0) + , mChild(this) +{ +} + +TabChild::~TabChild() +{ + // TODObsmedberg: destroy the window! +} + +bool +TabChild::Init(MessageLoop* aIOLoop, IPC::Channel* aChannel) +{ + mChild.Open(aChannel, aIOLoop); + return true; +} + +nsresult +TabChild::init(const MagicWindowHandle& parentWidget) +{ + printf("creating %d!\n", NS_IsMainThread()); + + gtk_init(NULL, NULL); + + nsCOMPtr webBrowser(do_CreateInstance(NS_WEBBROWSER_CONTRACTID)); + + nsCOMPtr baseWindow = do_QueryInterface(webBrowser); + + GtkWidget* win = gtk_plug_new((GdkNativeWindow)parentWidget); + gtk_widget_show(win); + baseWindow->InitWindow(win, 0, 0, 0, 0, 0); + + nsCOMPtr docShellItem(do_QueryInterface(baseWindow)); + docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper); + + baseWindow->Create(); + + baseWindow->SetVisibility(PR_TRUE); + + mWebNav = do_QueryInterface(webBrowser); + + // TODObz: create and embed a window! + return NS_ERROR_NOT_IMPLEMENTED; +} + +nsresult +TabChild::loadURL(const String& uri) +{ + printf("loading %s, %d\n", uri.c_str(), NS_IsMainThread()); + + return mWebNav->LoadURI(NS_ConvertUTF8toUTF16(uri.c_str()).get(), + nsIWebNavigation::LOAD_FLAGS_NONE, + NULL, NULL, NULL); +} + +nsresult +TabChild::move(const uint32_t& x, + const uint32_t& y, + const uint32_t& width, + const uint32_t& height) +{ + printf("[TabChild] MOVE to (x,y)=(%ud, %ud), (w,h)= (%ud, %ud)\n", + x, y, width, height); + + nsCOMPtr baseWin = do_QueryInterface(mWebNav); + baseWin->SetPositionAndSize(x, y, width, height, PR_TRUE); + return NS_OK; +} diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h new file mode 100644 index 000000000000..5ed60041befa --- /dev/null +++ b/dom/ipc/TabChild.h @@ -0,0 +1,45 @@ +/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */ + +#ifndef mozilla_tabs_TabChild_h +#define mozilla_tabs_TabChild_h + +#include "TabTypes.h" +#include "IFrameEmbeddingProtocol.h" +#include "IFrameEmbeddingProtocolChild.h" +#include "nsIWebNavigation.h" +#include "nsCOMPtr.h" + +namespace mozilla { +namespace tabs { + +class TabChild + : public IFrameEmbeddingProtocol::Child +{ +private: + typedef mozilla::ipc::String String; + +public: + TabChild(); + virtual ~TabChild(); + + bool Init(MessageLoop* aIOLoop, IPC::Channel* aChannel); + + virtual nsresult init(const MagicWindowHandle& parentWidget); + virtual nsresult loadURL(const String& uri); + virtual nsresult move(const uint32_t& x, + const uint32_t& y, + const uint32_t& width, + const uint32_t& height); + +private: + MagicWindowHandle mWidget; + IFrameEmbeddingProtocolChild mChild; + nsCOMPtr mWebNav; + + DISALLOW_EVIL_CONSTRUCTORS(TabChild); +}; + +} +} + +#endif // mozilla_tabs_TabChild_h diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp new file mode 100644 index 000000000000..267710515d08 --- /dev/null +++ b/dom/ipc/TabParent.cpp @@ -0,0 +1,64 @@ +#include "TabParent.h" + +#include "mozilla/ipc/GeckoThread.h" + +#include "nsIURI.h" + +using mozilla::ipc::BrowserProcessSubThread; + +template<> +struct RunnableMethodTraits +{ + static void RetainCallee(mozilla::tabs::TabParent* obj) { } + static void ReleaseCallee(mozilla::tabs::TabParent* obj) { } +}; + +namespace mozilla { +namespace tabs { + +TabParent::TabParent(MagicWindowHandle parentWidget) + : mSubprocess() + , mParent(this) + , mMonitor("mozilla.dom.ipc.TabParent") +{ + { + MonitorAutoEnter mon(mMonitor); + BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)-> + PostTask(FROM_HERE, NewRunnableMethod(this, &TabParent::LaunchSubprocess)); + mon.Wait(); + } + + mParent.Open(mSubprocess.GetChannel()); + + mParent.init(parentWidget); +} + +TabParent::~TabParent() +{ +} + +void +TabParent::LaunchSubprocess() +{ + MonitorAutoEnter mon(mMonitor); + mSubprocess.Launch(); + mon.Notify(); +} + +void +TabParent::LoadURL(nsIURI* aURI) +{ + nsCString spec; + aURI->GetSpec(spec); + + mParent.loadURL(spec.get()); +} + +void +TabParent::Move(PRUint32 x, PRUint32 y, PRUint32 width, PRUint32 height) +{ + mParent.move(x, y, width, height); +} + +} // namespace tabs +} // namespace mozilla diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h new file mode 100644 index 000000000000..1c0a6484d272 --- /dev/null +++ b/dom/ipc/TabParent.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: sw=4 ts=4 et : */ + +#ifndef mozilla_tabs_TabParent_h +#define mozilla_tabs_TabParent_h + +#include "TabTypes.h" +#include "IFrameEmbeddingProtocol.h" +#include "IFrameEmbeddingProtocolParent.h" +#include "TabProcessParent.h" + +#include "mozilla/Monitor.h" + +class nsIURI; + +namespace mozilla { +namespace tabs { + +class TabParent + : private IFrameEmbeddingProtocol::Parent +{ +public: + TabParent(MagicWindowHandle parentWidget); + virtual ~TabParent(); + + void LoadURL(nsIURI* aURI); + void Move(PRUint32 x, PRUint32 y, PRUint32 width, PRUint32 height); + +private: + void LaunchSubprocess(); + + TabProcessParent mSubprocess; + IFrameEmbeddingProtocolParent mParent; + + mozilla::Monitor mMonitor; +}; + +} // namespace tabs +} // namespace mozilla + +#endif diff --git a/dom/ipc/TabProcessParent.cpp b/dom/ipc/TabProcessParent.cpp new file mode 100644 index 000000000000..529dfaf2f028 --- /dev/null +++ b/dom/ipc/TabProcessParent.cpp @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: sw=4 ts=4 et : */ + +#include "TabProcessParent.h" + +#include "chrome/common/chrome_switches.h" + +namespace mozilla { +namespace tabs { + +char const *const TabProcessParent::kTabProcessName = "gecko-iframe" BIN_SUFFIX; + +TabProcessParent::TabProcessParent() +{ +} + +TabProcessParent::~TabProcessParent() +{ +} + +bool TabProcessParent::Launch() +{ + if (!CreateChannel()) + return false; + + FilePath exePath = + FilePath::FromWStringHack(CommandLine::ForCurrentProcess()->program()); + exePath = exePath.DirName(); + exePath = exePath.AppendASCII(kTabProcessName); + +#if defined(OS_POSIX) + int srcChannelFd, dstChannelFd; + channel().GetClientFileDescriptorMapping(&srcChannelFd, &dstChannelFd); + mFileMap.push_back(std::pair(srcChannelFd, dstChannelFd)); +#endif + + CommandLine cmdLine(exePath.ToWStringHack()); + cmdLine.AppendSwitchWithValue(switches::kProcessChannelID, channel_id()); + + base::ProcessHandle process; +#if defined(OS_POSIX) + base::LaunchApp(cmdLine.argv(), mFileMap, false, &process); +#else +#error Loser +#endif + + if (!process) + return false; + + SetHandle(process); + return true; +} + +} // namespace tabs +} // namespace mozilla diff --git a/dom/ipc/TabProcessParent.h b/dom/ipc/TabProcessParent.h new file mode 100644 index 000000000000..3b5723bd1822 --- /dev/null +++ b/dom/ipc/TabProcessParent.h @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: sw=4 ts=4 et : */ + +#ifndef mozilla_tabs_TabProcessParent_h +#define mozilla_tabs_TabProcessParent_h + +#include "mozilla/ipc/GeckoChildProcessHost.h" + +namespace mozilla { +namespace tabs { + +class TabProcessParent + : private mozilla::ipc::GeckoChildProcessHost +{ +public: + TabProcessParent(); + ~TabProcessParent(); + + /** + * Asynchronously launch the plugin process. + */ + bool Launch(); + + IPC::Channel* GetChannel() { + return channelp(); + } + + virtual bool CanShutdown() { + return true; + } + + base::WaitableEvent* GetShutDownEvent() { + return GetProcessEvent(); + } + +private: + static char const *const kTabProcessName; + + DISALLOW_EVIL_CONSTRUCTORS(TabProcessParent); +}; + +} +} + +#endif diff --git a/dom/ipc/TabThread.cpp b/dom/ipc/TabThread.cpp new file mode 100644 index 000000000000..feb6e9159344 --- /dev/null +++ b/dom/ipc/TabThread.cpp @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 et : + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Plugin App. + * + * The Initial Developer of the Original Code is + * Ben Turner . + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "TabThread.h" + +#include "prlink.h" + +#include "base/command_line.h" +#include "base/string_util.h" +#include "chrome/common/child_process.h" +#include "chrome/common/chrome_switches.h" + +using mozilla::ipc::GeckoThread; + +namespace mozilla { +namespace tabs { + +TabThread::TabThread() : + GeckoThread(), + mTab() +{ +} + +TabThread::~TabThread() +{ +} + +void +TabThread::Init() +{ + GeckoThread::Init(); + + // FIXME/cjones: set up channel stuff, etc. + + // FIXME owner_loop() is bad here + mTab.Init(owner_loop(), channel()); +} + +void +TabThread::CleanUp() +{ + GeckoThread::CleanUp(); +} + +} // namespace tabs +} // namespace mozilla diff --git a/dom/ipc/TabThread.h b/dom/ipc/TabThread.h new file mode 100644 index 000000000000..a0aa4a6b27ca --- /dev/null +++ b/dom/ipc/TabThread.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 et : + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Plugin App. + * + * The Initial Developer of the Original Code is + * Ben Turner . + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef dom_tabs_TabThread_h +#define dom_tabs_TabThread_h 1 + +#include "chrome/common/child_thread.h" +#include "base/file_path.h" + +#include "mozilla/ipc/GeckoThread.h" +#include "TabChild.h" + +#undef _MOZ_LOG +#define _MOZ_LOG(s) printf("[TabThread] %s", s) + +namespace mozilla { +namespace tabs { +//----------------------------------------------------------------------------- + +// The TabThread class represents a background thread where tab instances +// live. +class TabThread : public mozilla::ipc::GeckoThread { +public: + TabThread(); + ~TabThread(); + +private: + // Thread implementation: + virtual void Init(); + virtual void CleanUp(); + + TabChild mTab; + IPC::Channel* mChannel; + + DISALLOW_EVIL_CONSTRUCTORS(TabThread); +}; + +} // namespace tabs +} // namespace mozilla + +#endif // ifndef dom_tabs_TabThread_h diff --git a/dom/ipc/TabTypes.h b/dom/ipc/TabTypes.h new file mode 100644 index 000000000000..f1fc2b27dd9c --- /dev/null +++ b/dom/ipc/TabTypes.h @@ -0,0 +1,16 @@ +#ifndef mozilla_tabs_TabTypes_h +#define mozilla_tabs_TabTypes_h + +#ifdef XP_WIN +#include + +typedef HWND MagicWindowHandle; +#elif defined(MOZ_WIDGET_GTK2) +#include + +typedef XID MagicWindowHandle; +#else +#error Not implemented, stooge +#endif + +#endif diff --git a/dom/ipc/app/Makefile.in b/dom/ipc/app/Makefile.in new file mode 100644 index 000000000000..d2681185329f --- /dev/null +++ b/dom/ipc/app/Makefile.in @@ -0,0 +1,105 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Mozilla Plugin App. +# +# The Initial Developer of the Original Code is +# Ben Turner . +# Portions created by the Initial Developer are Copyright (C) 2009 +# the Initial Developer. All Rights Reserved. +# Chris Jones +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = dom + +## +## Build the child process that runs plugins +## +DEFINES += -DNO_NSPR_10_SUPPORT=1 + +PROGRAM = gecko-iframe$(BIN_SUFFIX) + +CPPSRCS = \ + TabApp.cpp \ + $(NULL) + +LIBS += \ + $(XPCOM_LIBS) \ + $(NSPR_LIBS) \ + $(NULL) + +# This switches $(INSTALL) to copy mode, like $(SYSINSTALL), so things that +# shouldn't get 755 perms need $(IFLAGS1) for either way of calling nsinstall. +NSDISTMODE = copy + +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk + +ifdef _MSC_VER +# Always enter a Windows program through wmain, whether or not we're +# a console application. +ifdef WINCE +WIN32_EXE_LDFLAGS += -ENTRY:mainWCRTStartup +else +WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup +endif +endif + +ifdef WINCE +EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME,corelibc) +endif + +ifeq ($(OS_ARCH),WINNT) +OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool) +OS_LIBS += $(call EXPAND_LIBNAME,usp10 msimg32) +endif + +include $(topsrcdir)/config/rules.mk + +ifeq ($(OS_ARCH),WINNT) +# +# Control the default heap size. +# This is the heap returned by GetProcessHeap(). +# As we use the CRT heap, the default size is too large and wastes VM. +# +# The default heap size is 1MB on Win32. +# The heap will grow if need be. +# +# Set it to 256k. See bug 127069. +# +ifndef GNU_CC +LDFLAGS += /HEAP:0x40000 +endif +endif diff --git a/dom/ipc/app/TabApp.cpp b/dom/ipc/app/TabApp.cpp new file mode 100644 index 000000000000..670b6e41a20b --- /dev/null +++ b/dom/ipc/app/TabApp.cpp @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 et : + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Plugin App. + * + * The Initial Developer of the Original Code is + * Ben Turner . + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones . + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsXPCOM.h" +#include "nsXULAppAPI.h" + + +// FIXME/cjones testing +#include + + +#ifdef XP_WIN +#include +// we want a wmain entry point +#include "nsWindowsWMain.cpp" +#endif + +class ScopedLogging +{ +public: + ScopedLogging() { NS_LogInit(); } + ~ScopedLogging() { NS_LogTerm(); } +}; + +int +main(int argc, char* argv[]) +{ + ScopedLogging log; + nsresult rv = XRE_InitChildProcess(argc, argv, "TabThread"); + NS_ENSURE_SUCCESS(rv, 1); +} diff --git a/dom/ipc/test.xul b/dom/ipc/test.xul new file mode 100644 index 000000000000..934509c0772e --- /dev/null +++ b/dom/ipc/test.xul @@ -0,0 +1,26 @@ + + + + + + + + + + + + +