From 9eb95d4aed12184f7c18d27ef4a023844b3f9bd4 Mon Sep 17 00:00:00 2001 From: "danm%netscape.com" Date: Tue, 6 Nov 2001 01:19:39 +0000 Subject: [PATCH] consolidating nsIWebBrowserChrome::CreateBrowserWindow and nsIWindowCreator::CreateChromeWindow. part of bug 88229 r=hyatt,rpotts git-svn-id: svn://10.0.0.236/trunk@107382 18797224-902f-48f8-a5cc-f745e15eee43 --- .../docshell/base/nsIDocShellTreeOwner.idl | 10 - .../src/control/WebBrowserContainer.cpp | 31 --- .../embedding/browser/gtk/src/EmbedWindow.cpp | 37 ---- .../photon/src/WebBrowserContainer.cpp | 36 ---- .../powerplant/source/CWebBrowserChrome.cpp | 22 -- .../webBrowser/nsDocShellTreeOwner.cpp | 28 --- .../webBrowser/nsIWebBrowserChrome.idl | 12 -- .../public/nsPIWindowWatcher.idl | 32 ++- .../windowwatcher/src/nsWindowWatcher.cpp | 204 ++++++++++++++---- .../windowwatcher/src/nsWindowWatcher.h | 3 + .../embedding/tests/mfcembed/BrowserImpl.cpp | 16 -- .../tests/winEmbed/WebBrowserChrome.cpp | 31 --- mozilla/webshell/tests/viewer/Makefile.in | 3 + mozilla/webshell/tests/viewer/makefile.win | 3 + .../webshell/tests/viewer/nsBrowserWindow.cpp | 35 ++- .../webshell/tests/viewer/nsBrowserWindow.h | 7 +- mozilla/webshell/tests/viewer/nsViewerApp.cpp | 25 +++ mozilla/webshell/tests/viewer/nsViewerApp.h | 1 + .../tests/viewer/nsWebBrowserChrome.cpp | 44 ++-- .../webshell/tests/viewer/nsWindowCreator.cpp | 91 ++++++++ .../webshell/tests/viewer/nsWindowCreator.h | 61 ++++++ mozilla/xpfe/appshell/public/nsIXULWindow.idl | 115 +++++----- .../xpfe/appshell/src/nsChromeTreeOwner.cpp | 8 +- .../xpfe/appshell/src/nsContentTreeOwner.cpp | 23 +- mozilla/xpfe/appshell/src/nsXULWindow.cpp | 37 ++-- mozilla/xpfe/appshell/src/nsXULWindow.h | 6 +- mozilla/xpfe/bootstrap/Makefile.in | 2 +- mozilla/xpfe/bootstrap/nsWindowCreator.cpp | 56 ++--- 28 files changed, 538 insertions(+), 441 deletions(-) create mode 100644 mozilla/webshell/tests/viewer/nsWindowCreator.cpp create mode 100644 mozilla/webshell/tests/viewer/nsWindowCreator.h diff --git a/mozilla/docshell/base/nsIDocShellTreeOwner.idl b/mozilla/docshell/base/nsIDocShellTreeOwner.idl index 4c7166a87e3..cc32b5f027b 100644 --- a/mozilla/docshell/base/nsIDocShellTreeOwner.idl +++ b/mozilla/docshell/base/nsIDocShellTreeOwner.idl @@ -65,16 +65,6 @@ interface nsIDocShellTreeOwner : nsISupports */ void sizeShellTo(in nsIDocShellTreeItem shell, in long cx, in long cy); - /* - Tells the implementer of this interface to create a new window. This is - a new logical window. Meaning in some implementations the result may not - be an actual new window, but rather a new tab or view in an existing - window. What is returned is the new DocShellTreeItem from which the - internals can operate on. This most often will be called when there is - a need for a new JS window, etc. - */ - nsIDocShellTreeItem getNewWindow(in long aChromeFlags); - /* Sets the persistence of different attributes of the window. */ diff --git a/mozilla/embedding/browser/activex/src/control/WebBrowserContainer.cpp b/mozilla/embedding/browser/activex/src/control/WebBrowserContainer.cpp index 96488b01355..0561583f89f 100644 --- a/mozilla/embedding/browser/activex/src/control/WebBrowserContainer.cpp +++ b/mozilla/embedding/browser/activex/src/control/WebBrowserContainer.cpp @@ -592,37 +592,6 @@ CWebBrowserContainer::SetChromeFlags(PRUint32 aChromeFlags) } -NS_IMETHODIMP -CWebBrowserContainer::CreateBrowserWindow(PRUint32 chromeFlags, PRInt32 aX, PRInt32 aY, PRInt32 aCX, PRInt32 aCY, nsIWebBrowser **_retval) -{ - IDispatch *pDispNew = NULL; - VARIANT_BOOL bCancel = VARIANT_FALSE; - - *_retval = nsnull; - - // Test if the event sink can give us a new window to navigate into - m_pEvents2->Fire_NewWindow2(&pDispNew, &bCancel); - - if ((bCancel == VARIANT_FALSE) && pDispNew) - { - CComQIPtr cpBridge = pDispNew; - if (cpBridge) - { - nsIWebBrowser *browser = nsnull; - cpBridge->GetWebBrowser((void **) &browser); - if (browser) - { - *_retval = browser; - return NS_OK; - } - } - pDispNew->Release(); - } - - return NS_ERROR_FAILURE; -} - - NS_IMETHODIMP CWebBrowserContainer::DestroyBrowserWindow(void) { diff --git a/mozilla/embedding/browser/gtk/src/EmbedWindow.cpp b/mozilla/embedding/browser/gtk/src/EmbedWindow.cpp index 8a4eb078766..3e273c20b37 100644 --- a/mozilla/embedding/browser/gtk/src/EmbedWindow.cpp +++ b/mozilla/embedding/browser/gtk/src/EmbedWindow.cpp @@ -169,43 +169,6 @@ EmbedWindow::SetChromeFlags(PRUint32 aChromeFlags) return NS_OK; } -NS_IMETHODIMP -EmbedWindow::CreateBrowserWindow(PRUint32 aChromeFlags, - PRInt32 aX, PRInt32 aY, - PRInt32 aCX, PRInt32 aCY, - nsIWebBrowser **_retval) -{ - GtkMozEmbed *newEmbed = nsnull; - - gtk_signal_emit(GTK_OBJECT(mOwner->mOwningWidget), - moz_embed_signals[NEW_WINDOW], - &newEmbed, (guint)aChromeFlags); - - if (!newEmbed) - return NS_ERROR_FAILURE; - - // The window _must_ be realized before we pass it back to the - // function that created it. Functions that create new windows - // will do things like GetDocShell() and the widget has to be - // realized before that can happen. - gtk_widget_realize(GTK_WIDGET(newEmbed)); - - EmbedPrivate *newEmbedPrivate = NS_STATIC_CAST(EmbedPrivate *, - newEmbed->data); - - // set the chrome flag on the new window if it's a chrome open - if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) - newEmbedPrivate->mIsChrome = PR_TRUE; - - newEmbedPrivate->mWindow->GetWebBrowser(_retval); - - if (*_retval) - return NS_OK; - - return NS_ERROR_FAILURE; - -} - NS_IMETHODIMP EmbedWindow::DestroyBrowserWindow(void) { diff --git a/mozilla/embedding/browser/photon/src/WebBrowserContainer.cpp b/mozilla/embedding/browser/photon/src/WebBrowserContainer.cpp index 6b5b3625730..571f34caddf 100644 --- a/mozilla/embedding/browser/photon/src/WebBrowserContainer.cpp +++ b/mozilla/embedding/browser/photon/src/WebBrowserContainer.cpp @@ -714,42 +714,6 @@ CWebBrowserContainer::SizeShellTo(nsIDocShellTreeItem* aShell, return NS_OK; } -NS_IMETHODIMP CWebBrowserContainer::GetNewWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem) -{ - PtMozillaWidget_t *nmoz, *moz = (PtMozillaWidget_t *)m_pOwner; - PtCallbackList_t *cb; - PtCallbackInfo_t cbinfo; - PtMozillaNewWindowCb_t nwin; - - *aDocShellTreeItem = nsnull; - - if (!moz->new_window_cb) - return NS_ERROR_FAILURE; - - memset(&cbinfo, 0, sizeof(cbinfo)); - cbinfo.cbdata = &nwin; - cbinfo.reason = Pt_CB_MOZ_NEW_WINDOW; - cb = moz->new_window_cb; - nwin.window_flags = aChromeFlags; - - PtSetParentWidget(NULL); - if (PtInvokeCallbackList(cb, (PtWidget_t *) moz, &cbinfo) == Pt_CONTINUE) - { - nmoz = (PtMozillaWidget_t *) nwin.widget; - - nsCOMPtr webBrowserAsReq(do_QueryInterface(nmoz->MyBrowser->WebBrowser)); - nsCOMPtr docShell(do_GetInterface(webBrowserAsReq)); - NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); - - NS_ENSURE_SUCCESS(CallQueryInterface(docShell, aDocShellTreeItem),NS_ERROR_FAILURE); - return NS_OK; - } - - return NS_ERROR_FAILURE; -} - - /////////////////////////////////////////////////////////////////////////////// // Data streaming interface diff --git a/mozilla/embedding/browser/powerplant/source/CWebBrowserChrome.cpp b/mozilla/embedding/browser/powerplant/source/CWebBrowserChrome.cpp index efad965a82c..f47ad4e7140 100644 --- a/mozilla/embedding/browser/powerplant/source/CWebBrowserChrome.cpp +++ b/mozilla/embedding/browser/powerplant/source/CWebBrowserChrome.cpp @@ -152,28 +152,6 @@ NS_IMETHODIMP CWebBrowserChrome::SetChromeFlags(PRUint32 aChromeMask) return NS_ERROR_FAILURE; } - -NS_IMETHODIMP CWebBrowserChrome::CreateBrowserWindow(PRUint32 chromeMask, PRInt32 aX, PRInt32 aY, PRInt32 aCX, PRInt32 aCY, nsIWebBrowser **aWebBrowser) -{ - NS_ENSURE_ARG_POINTER(aWebBrowser); - *aWebBrowser = nsnull; - - CBrowserWindow *theWindow; - try - { - // CreateWindow can throw an we're being called from mozilla, so we need to catch - theWindow = CBrowserWindow::CreateWindow(chromeMask, aCX, aCY); - } - catch (...) - { - theWindow = nsnull; - } - NS_ENSURE_TRUE(theWindow, NS_ERROR_FAILURE); - CBrowserShell *aBrowserShell = theWindow->GetBrowserShell(); - NS_ENSURE_TRUE(aBrowserShell, NS_ERROR_FAILURE); - return aBrowserShell->GetWebBrowser(aWebBrowser); -} - NS_IMETHODIMP CWebBrowserChrome::DestroyBrowserWindow() { mInModalLoop = false; diff --git a/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp b/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp index 2f56421978e..7c18d7d2a3e 100644 --- a/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp +++ b/mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp @@ -432,34 +432,6 @@ NS_IMETHODIMP nsDocShellTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem, return mWebBrowserChrome->SizeBrowserTo(browserCX, browserCY); } -NS_IMETHODIMP nsDocShellTreeOwner::GetNewWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem) -{ - nsresult rv; - - if(mTreeOwner) - return mTreeOwner->GetNewWindow(aChromeFlags, aDocShellTreeItem); - - *aDocShellTreeItem = nsnull; - - NS_ENSURE_TRUE(mWebBrowserChrome, NS_ERROR_FAILURE); - aChromeFlags &= ~(nsIWebBrowserChrome::CHROME_WITH_SIZE | nsIWebBrowserChrome::CHROME_WITH_POSITION); - - nsCOMPtr webBrowser; - rv = mWebBrowserChrome->CreateBrowserWindow(PRUint32(aChromeFlags), - -1, -1, -1, -1, // this is kind of a problem - getter_AddRefs(webBrowser)); - if (NS_SUCCEEDED(rv) && webBrowser) { - nsCOMPtr asreq(do_QueryInterface(webBrowser)); - if (asreq) { - nsCOMPtr asshell(do_GetInterface(asreq)); - if (asshell) - rv = CallQueryInterface(asshell, aDocShellTreeItem); - } - } - return rv; -} - NS_IMETHODIMP nsDocShellTreeOwner::SetPersistence(PRBool aPersistPosition, PRBool aPersistSize, diff --git a/mozilla/embedding/browser/webBrowser/nsIWebBrowserChrome.idl b/mozilla/embedding/browser/webBrowser/nsIWebBrowserChrome.idl index 9b9332b92de..4c9c9d45e35 100644 --- a/mozilla/embedding/browser/webBrowser/nsIWebBrowserChrome.idl +++ b/mozilla/embedding/browser/webBrowser/nsIWebBrowserChrome.idl @@ -95,18 +95,6 @@ interface nsIWebBrowserChrome : nsISupports */ attribute unsigned long chromeFlags; - /* - Asks the implementer of this interface to create a new webbrowser - object and return the nsIWebBrowser interface to it. The chrome - flags indicate the style of the surrounding frame window and - associated chrome. The position parameters should be ignored - unless the CHROME_WITH_POSITION chrome flags is set. The size - parameters should be ignored unless the CHROME_WITH_SIZE chrome flag - is set. - */ - nsIWebBrowser createBrowserWindow(in unsigned long chromeFlags, - in long aX, in long aY, in long aCX, in long aCY); - /* Asks the implementer to destroy the window associated with this webbrowser object. diff --git a/mozilla/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl b/mozilla/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl index 8eb69ee7e23..54b86fa8dec 100644 --- a/mozilla/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl +++ b/mozilla/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl @@ -55,8 +55,7 @@ interface nsPIWindowWatcher : nsISupports void removeWindow(in nsIDOMWindow aWindow); /** Like the public interface's open(), but can deal with openDialog - style arguments. The exact definition of this method is temporary - pending the XPIDL rewrite of the DOM. + style arguments. @param aParent parent window, if any. null if not. @param aURL url to which to open the new window. Must already be escaped, if applicable. can be null. @@ -72,6 +71,35 @@ interface nsPIWindowWatcher : nsISupports in string aName, in string aFeatures, in boolean aDialog, in PRUint32 argc, in jsvalptr argv); + /** One of several internal-use stages in creating a new chrome window. + The interface(s) for creating a window are arguably +
+      1) nsIWindowWatcher::openWindow (public interface)
+      2) nsPIWindowWatcher::openWindowJS (internal, called by above)
+      3) nsPIWindowWatcher::createChromeWindow (internal, called by above)
+      4) nsIWindowCreator::createChromeWindow (implemented by the embedding app)
+      
+ The fourth level is implementation-dependent and must be supplied. + It must create the window (of course) and synchronously load some + appropriate URL into the embedded docshell, guaranteeing that the + docshell is ready for use as soon as the function returns. + The third level wraps the fourth with some internal bookkeeping + necessary for the expected implementation of the fourth level + (a captive event loop) to work. Internally to Mozilla code, the + fourth level should never be accessed directly except through + the third level. The second level allows JavaScript-style parameters + to be passed. The top level is nominally the only public access point. + @param aParent parent window, or null if no parent. + @param aChromeFlags chrome features from nsIWebBrowserChrome. + The position parameters should be ignored + unless the CHROME_WITH_POSITION chrome flags is set. + The size parameters should be ignored unless + the CHROME_WITH_SIZE chrome flag is set. + @return the new window + */ + nsIWebBrowserChrome createChromeWindow(in nsIWebBrowserChrome aParent, + in PRUint32 aChromeFlags); + }; %{C++ diff --git a/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp b/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp index deae25edeea..c39854fe7e2 100644 --- a/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp +++ b/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp @@ -43,9 +43,9 @@ #include "jscntxt.h" #include "nsAutoLock.h" #include "nsCRT.h" -#include "nsWWJSUtils.h" #include "nsNetUtil.h" #include "nsPrompt.h" +#include "nsWWJSUtils.h" #include "plstr.h" #include "nsIBaseWindow.h" @@ -74,7 +74,6 @@ #include "nsIWebNavigation.h" #include "nsIWindowCreator.h" #include "nsIXPConnect.h" -#include "nsReadableUtils.h" #ifdef XP_UNIX // please see bug 78421 for the eventual "right" fix for this @@ -91,8 +90,6 @@ #include "nsIWeakReference.h" #endif -#define NOTIFICATION_CLOSED NS_LITERAL_CSTRING("domwindowclosed") - #ifdef HAVE_LAME_APPSHELL static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); #endif @@ -542,17 +539,13 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent, if (!newDocShellItem) { windowIsNew = PR_TRUE; + nsCOMPtr parentChrome(do_GetInterface(parentTreeOwner)); + // is the parent (if any) modal? if so, we must be, too. PRBool weAreModal = PR_FALSE; - if (parentTreeOwner) { - nsCOMPtr parentRequestor(do_QueryInterface(parentTreeOwner)); - if (parentRequestor) { - nsCOMPtr parentChrome; - parentRequestor->GetInterface(NS_GET_IID(nsIWebBrowserChrome), getter_AddRefs(parentChrome)); - if (parentChrome) - parentChrome->IsWindowModal(&weAreModal); - } - } + if (parentChrome) + parentChrome->IsWindowModal(&weAreModal); + if (weAreModal || (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL)) { rv = queueGuard.Push(); if (NS_SUCCEEDED(rv)) { @@ -561,25 +554,20 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent, chromeFlags |= nsIWebBrowserChrome::CHROME_MODAL | nsIWebBrowserChrome::CHROME_DEPENDENT; } } - if (parentTreeOwner) - parentTreeOwner->GetNewWindow(chromeFlags, getter_AddRefs(newDocShellItem)); - else if (mWindowCreator) { + + NS_ASSERTION(mWindowCreator, "attempted to open a new window with no WindowCreator"); + if (mWindowCreator) { nsCOMPtr newChrome; - mWindowCreator->CreateChromeWindow(0, chromeFlags, getter_AddRefs(newChrome)); + CreateChromeWindow(parentChrome, chromeFlags, getter_AddRefs(newChrome)); if (newChrome) { - nsCOMPtr thing(do_QueryInterface(newChrome)); - if (thing) { - /* It might be a chrome nsXULWindow, in which case it won't have - an nsIDOMWindow (primary content shell). But in that case, it'll - be able to hand over an nsIDocShellTreeItem directly. */ - // XXX got the order right? - nsCOMPtr newWindow; - thing->GetInterface(NS_GET_IID(nsIDOMWindow), getter_AddRefs(newWindow)); - if (newWindow) - GetWindowTreeItem(newWindow, getter_AddRefs(newDocShellItem)); - if (!newDocShellItem) - thing->GetInterface(NS_GET_IID(nsIDocShellTreeItem), getter_AddRefs(newDocShellItem)); - } + /* It might be a chrome nsXULWindow, in which case it won't have + an nsIDOMWindow (primary content shell). But in that case, it'll + be able to hand over an nsIDocShellTreeItem directly. */ + nsCOMPtr newWindow(do_GetInterface(newChrome)); + if (newWindow) + GetWindowTreeItem(newWindow, getter_AddRefs(newDocShellItem)); + if (!newDocShellItem) + newDocShellItem = do_GetInterface(newChrome); } } } @@ -703,15 +691,8 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent, if (windowIsModal) { nsCOMPtr newTreeOwner; - nsCOMPtr newRequestor; - nsCOMPtr newChrome; - newDocShellItem->GetTreeOwner(getter_AddRefs(newTreeOwner)); - if (newTreeOwner) - newRequestor = do_QueryInterface(newTreeOwner); - if (newRequestor) - newRequestor->GetInterface(NS_GET_IID(nsIWebBrowserChrome), getter_AddRefs(newChrome)); - + nsCOMPtr newChrome(do_GetInterface(newTreeOwner)); if (newChrome) newChrome->ShowAsModal(); NS_ASSERTION(newChrome, "show modal window failed: no available chrome"); @@ -720,6 +701,23 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent, return NS_OK; } +NS_IMETHODIMP +nsWindowWatcher::CreateChromeWindow(nsIWebBrowserChrome *aParent, + PRUint32 aChromeFlags, + nsIWebBrowserChrome **_retval) +{ + NS_ASSERTION(mWindowCreator, "can't proceed without a window creator!"); + if (!mWindowCreator) + return NS_ERROR_FAILURE; + + nsresult rv; + + rv = mWindowCreator->CreateChromeWindow(aParent, aChromeFlags, _retval); + if (NS_SUCCEEDED(rv)) + rv = InitializeDocshell(*_retval); + return rv; +} + NS_IMETHODIMP nsWindowWatcher::RegisterNotification(nsIObserver *aObserver) { @@ -1317,6 +1315,136 @@ nsWindowWatcher::FindItemWithName( return rv; } +#define INITSYNCH +//#undef INITSYNCH +#ifndef INITSYNCH + +// also makefile.win and nsDocshellLoadProgress.* +#include "nsDocshellLoadProgress.h" +#include "nsIAppShell.h" +#include "nsWidgetsCID.h" +static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); + +static void RunEventLoop(PRBool *aRunCondition) { + + nsCOMPtr appShell(do_CreateInstance(kAppShellCID)); + if (!appShell) return; + + appShell->Create(0, nsnull); + appShell->Spinup(); + + nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1")); + nsresult rv = NS_OK; + if (stack && NS_SUCCEEDED(stack->Push(nsnull))) { + while (NS_SUCCEEDED(rv) && *aRunCondition) { + void* data; + PRBool isRealEvent; + + rv = appShell->GetNativeEvent(isRealEvent, data); + if (NS_SUCCEEDED(rv)) + appShell->DispatchNativeEvent(isRealEvent, data); + } + JSContext* cx; + stack->Pop(&cx); + NS_ASSERTION(cx == nsnull, "JSContextStack mismatch"); + } else + rv = NS_ERROR_FAILURE; + + appShell->Spindown(); +} + +#endif + + +/* Synchronously load about:blank to force docshell initialization. + This will allow, for instance, script executed immediately following + window.open to access the docshell (which can be something as + straightforward as newWindow.document.write, or something more indirect, + such as window.resizeTo.) This step is unnecessary in Mozilla, since + its chrome windows contain XUL docshells, but is important for most + (all) embedding apps. */ +nsresult +nsWindowWatcher::InitializeDocshell(nsIWebBrowserChrome *aBrowserChrome) +{ +#ifdef INITSYNCH + + nsCOMPtr docshell; + + // embedded window path: docshell corresponding to the primary content + nsCOMPtr browserWindow(do_GetInterface(aBrowserChrome)); + if (browserWindow) { + nsCOMPtr sgo(do_QueryInterface(browserWindow)); + if (sgo) + sgo->GetDocShell(getter_AddRefs(docshell)); + } + // XUL Window path + // XXX: teach nsContentTreeOwner to give up its nsIDocShell + if (!docshell) { + } + + // Asking Mozilla's docshell for its document will force it + // to generate one, and its content viewer. This is just what + // we need here. But it is a rather sneaky back door. + if (docshell) + nsCOMPtr domdoc(do_GetInterface(docshell)); + +#else + + NS_ASSERTION(mWindowCreator, "can't proceed without a window creator!"); + if (!mWindowCreator) + return NS_ERROR_FAILURE; + + nsCOMPtr browser; + aBrowserChrome->GetWebBrowser(getter_AddRefs(browser)); + if (!browser) { + /* All embedded apps must implement this, but Mozilla doesn't. And handily, + Mozilla doesn't need any special docshell initialization and in fact + doesn't want it. So exit and be happy. This is a small worry; we won't + catch legitimate cases of embedded apps missing their WebBrowsers. */ + return NS_OK; + } + + // create a progress listener + PRBool docshellLoading = PR_TRUE; + nsDocshellLoadProgress *progress = new nsDocshellLoadProgress(&docshellLoading); + if (!progress) + return NS_ERROR_FAILURE; + + // (note that this COM ref going out of scope will delete the object) + nsCOMPtr supWeak(do_QueryInterface(NS_STATIC_CAST(nsISupportsWeakReference *, progress))); + if (!supWeak) { + delete progress; + return NS_ERROR_FAILURE; + } + nsCOMPtr weakListener; + supWeak->GetWeakReference(getter_AddRefs(weakListener)); + if (!weakListener) + return NS_ERROR_FAILURE; + + // attach our new progress listener to the WebBrowser + browser->AddWebBrowserListener(weakListener, nsIWebProgressListener::GetIID()); + + // start a load of about:blank + nsCOMPtr webNav(do_QueryInterface(browser)); + if (webNav) { + EventQueueAutoPopper queueGuard; + queueGuard.Push(); + + webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(), nsIWebNavigation::LOAD_FLAGS_NONE); + + // sit-'n-spin until it finishes loading + NS_WARNING("open-window entering synchronous docshell load"); + RunEventLoop(&docshellLoading); + } + + browser->RemoveWebBrowserListener(weakListener, nsIWebProgressListener::GetIID()); + + NS_WARNING("finished synchronous docshell load"); +#endif + + return NS_OK; +} + /* Fetch the nsIDOMWindow corresponding to the given nsIDocShellTreeItem. This forces the creation of a script context, if one has not already been created. Note it also sets the window's opener to the parent, diff --git a/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.h b/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.h index 7730787c3fa..db1bb94768a 100644 --- a/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.h +++ b/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.h @@ -55,6 +55,7 @@ class nsIURI; class nsIDocShellTreeItem; class nsIDocShellTreeOwner; +class nsIWebBrowserChrome; class nsString; class nsWatcherWindowEnumerator; struct JSContext; @@ -89,6 +90,8 @@ private: nsresult FindItemWithName(const PRUnichar *aName, nsIDocShellTreeItem **aFoundItem); + nsresult InitializeDocshell(nsIWebBrowserChrome *aChromeWindow); + static JSContext *GetJSContextFromWindow(nsIDOMWindow *aWindow); static JSContext *GetJSContextFromCallStack(); static nsresult URIfromURL(const char *aURL, diff --git a/mozilla/embedding/tests/mfcembed/BrowserImpl.cpp b/mozilla/embedding/tests/mfcembed/BrowserImpl.cpp index cee65ab36c4..0406cdfa093 100644 --- a/mozilla/embedding/tests/mfcembed/BrowserImpl.cpp +++ b/mozilla/embedding/tests/mfcembed/BrowserImpl.cpp @@ -192,22 +192,6 @@ NS_IMETHODIMP CBrowserImpl::SetChromeFlags(PRUint32 aChromeMask) return NS_ERROR_NOT_IMPLEMENTED; } -// Gets called in response to create a new browser window. -// Ex: In response to a JavaScript Window.Open() call -// -// -NS_IMETHODIMP CBrowserImpl::CreateBrowserWindow(PRUint32 chromeMask, PRInt32 aX, PRInt32 aY, PRInt32 aCX, PRInt32 aCY, nsIWebBrowser **aWebBrowser) -{ - if(! m_pBrowserFrameGlue) - return NS_ERROR_FAILURE; - - if(m_pBrowserFrameGlue->CreateNewBrowserFrame(chromeMask, - aX, aY, aCX, aCY, aWebBrowser)) - return NS_OK; - else - return NS_ERROR_FAILURE; -} - // Will get called in response to JavaScript window.close() // NS_IMETHODIMP CBrowserImpl::DestroyBrowserWindow() diff --git a/mozilla/embedding/tests/winEmbed/WebBrowserChrome.cpp b/mozilla/embedding/tests/winEmbed/WebBrowserChrome.cpp index 287471c7c9b..03c09b04149 100644 --- a/mozilla/embedding/tests/winEmbed/WebBrowserChrome.cpp +++ b/mozilla/embedding/tests/winEmbed/WebBrowserChrome.cpp @@ -178,37 +178,6 @@ NS_IMETHODIMP WebBrowserChrome::SetChromeFlags(PRUint32 aChromeMask) return NS_OK; } -NS_IMETHODIMP WebBrowserChrome::CreateBrowserWindow(PRUint32 aChromeFlags, - PRInt32 aX, PRInt32 aY, - PRInt32 aCX, PRInt32 aCY, - nsIWebBrowser **_retval) -{ - NS_ENSURE_ARG_POINTER(_retval); - *_retval = nsnull; - - // Create the chrome object. Note that it leaves this function - // with an extra reference so that it can released correctly during - // destruction (via Win32UI::Destroy) - - nsresult rv; - - nsIWebBrowserChrome *parent = aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT ? this : 0; - - nsCOMPtr newChrome; - rv = AppCallbacks::CreateBrowserWindow(aChromeFlags, parent, - getter_AddRefs(newChrome)); - if (NS_SUCCEEDED(rv)) - { - newChrome->GetWebBrowser(_retval); - // leave chrome windows hidden until the chrome is loaded - if (!(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) - WebBrowserChromeUI::ShowWindow(this, PR_TRUE); - } - - return rv; -} - - NS_IMETHODIMP WebBrowserChrome::DestroyBrowserWindow(void) { WebBrowserChromeUI::Destroy(this); diff --git a/mozilla/webshell/tests/viewer/Makefile.in b/mozilla/webshell/tests/viewer/Makefile.in index d3c180c21c8..0c35273cbcf 100644 --- a/mozilla/webshell/tests/viewer/Makefile.in +++ b/mozilla/webshell/tests/viewer/Makefile.in @@ -31,6 +31,7 @@ DIRS := public MODULE = webshell_tests REQUIRES = xpcom \ string \ + embed_base \ webshell \ widget \ gfx \ @@ -50,6 +51,7 @@ REQUIRES = xpcom \ intl \ editor \ cookie \ + windowwatcher \ xpconnect \ $(NULL) @@ -70,6 +72,7 @@ CPPSRCS = \ nsViewerApp.cpp \ nsWebCrawler.cpp \ nsWebBrowserChrome.cpp \ + nsWindowCreator.cpp \ $(NULL) ifeq (,$(filter beos os2 photon mac,$(MOZ_WIDGET_TOOLKIT))) diff --git a/mozilla/webshell/tests/viewer/makefile.win b/mozilla/webshell/tests/viewer/makefile.win index c3e24478792..f991628bef8 100644 --- a/mozilla/webshell/tests/viewer/makefile.win +++ b/mozilla/webshell/tests/viewer/makefile.win @@ -23,6 +23,7 @@ DEPTH=..\..\.. MODULE=viewer REQUIRES = xpcom \ string \ + embed_base \ webshell \ widget \ layout \ @@ -44,6 +45,7 @@ REQUIRES = xpcom \ gfx \ content \ wallet \ + windowwatcher \ js \ $(NULL) @@ -81,6 +83,7 @@ OBJS = \ .\$(OBJDIR)\nsWinMain.obj \ .\$(OBJDIR)\JSConsole.obj \ .\$(OBJDIR)\nsWidgetSupport.obj \ + .\$(OBJDIR)\nsWindowCreator.obj \ $(NULL) LLIBS= \ diff --git a/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp b/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp index 93e7de5abf5..755e6cca25c 100644 --- a/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp +++ b/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp @@ -1345,36 +1345,27 @@ nsBrowserWindow::~nsBrowserWindow() } } -NS_IMPL_ADDREF(nsBrowserWindow) -NS_IMPL_RELEASE(nsBrowserWindow) +NS_IMPL_ISUPPORTS4(nsBrowserWindow, nsIBaseWindow, nsIInterfaceRequestor, nsIProgressEventSink, nsIWebShellContainer); nsresult -nsBrowserWindow::QueryInterface(const nsIID& aIID, - void** aInstancePtrResult) +nsBrowserWindow::GetInterface(const nsIID& aIID, + void** aInstancePtrResult) { - NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer"); - if (nsnull == aInstancePtrResult) { + nsresult rv; + + NS_PRECONDITION(aInstancePtrResult, "null pointer"); + if (!aInstancePtrResult) return NS_ERROR_NULL_POINTER; - } *aInstancePtrResult = NULL; - if (aIID.Equals(kIWebShellContainerIID)) { - *aInstancePtrResult = (void*) ((nsIWebShellContainer*)this); - NS_ADDREF_THIS(); - return NS_OK; + if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome))) { + rv = EnsureWebBrowserChrome(); + if (NS_SUCCEEDED(rv)) + return mWebBrowserChrome->QueryInterface(aIID, aInstancePtrResult); } - if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) { - *aInstancePtrResult = (void*) ((nsIProgressEventSink*)this); - NS_ADDREF_THIS(); - return NS_OK; - } - if (aIID.Equals(kISupportsIID)) { - *aInstancePtrResult = (void*) ((nsISupports*)((nsIWebShellContainer*)this)); - NS_ADDREF_THIS(); - return NS_OK; - } - return NS_NOINTERFACE; + + return QueryInterface(aIID, aInstancePtrResult); } nsresult diff --git a/mozilla/webshell/tests/viewer/nsBrowserWindow.h b/mozilla/webshell/tests/viewer/nsBrowserWindow.h index 8f2726e2f24..65535f0bc16 100644 --- a/mozilla/webshell/tests/viewer/nsBrowserWindow.h +++ b/mozilla/webshell/tests/viewer/nsBrowserWindow.h @@ -46,7 +46,7 @@ // Interfaces Needed #include "nsIBaseWindow.h" - +#include "nsIInterfaceRequestor.h" #include "nsIWebBrowser.h" #include "nsIStreamListener.h" @@ -83,6 +83,7 @@ class nsIContent; * Abstract base class for our test app's browser windows */ class nsBrowserWindow : public nsIBaseWindow, + public nsIInterfaceRequestor, public nsIProgressEventSink, public nsIWebShellContainer { @@ -91,11 +92,9 @@ friend class nsWebBrowserChrome; public: NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW - // nsISupports NS_DECL_ISUPPORTS - - // nsIBaseWindow NS_DECL_NSIBASEWINDOW + NS_DECL_NSIINTERFACEREQUESTOR protected: void DestroyWidget(nsISupports* aWidget); diff --git a/mozilla/webshell/tests/viewer/nsViewerApp.cpp b/mozilla/webshell/tests/viewer/nsViewerApp.cpp index c516012a6d9..0878cc53aee 100644 --- a/mozilla/webshell/tests/viewer/nsViewerApp.cpp +++ b/mozilla/webshell/tests/viewer/nsViewerApp.cpp @@ -46,8 +46,10 @@ #include "nsViewerApp.h" #include "nsBrowserWindow.h" #include "nsWidgetsCID.h" +#include "nsWindowCreator.h" #include "nsIAppShell.h" #include "nsIPref.h" +#include "nsIWindowWatcher.h" // Form Processor #include "nsIFormProcessor.h" @@ -321,6 +323,8 @@ nsViewerApp::Initialize(int argc, char** argv) return rv; } + InitializeWindowCreator(); + // Create widget application shell rv = nsComponentManager::CreateInstance(kAppShellCID, nsnull, kIAppShellIID, (void**)&mAppShell); @@ -345,6 +349,27 @@ nsViewerApp::Initialize(int argc, char** argv) return rv; } +/* InitializeWindowCreator creates and hands off an object with a callback + to a window creation function. This is how all new windows are opened, + except any created directly by the viewer app. */ +nsresult +nsViewerApp::InitializeWindowCreator() +{ + // create an nsWindowCreator and give it to the WindowWatcher service + nsWindowCreator *creatorCallback = new nsWindowCreator(this); + if (creatorCallback) { + nsCOMPtr windowCreator(dont_QueryInterface(NS_STATIC_CAST(nsIWindowCreator *, creatorCallback))); + if (windowCreator) { + nsCOMPtr wwatch(do_GetService("@mozilla.org/embedcomp/window-watcher;1")); + if (wwatch) { + wwatch->SetWindowCreator(windowCreator); + return NS_OK; + } + } + } + return NS_ERROR_FAILURE; +} + nsresult nsViewerApp::Exit() { diff --git a/mozilla/webshell/tests/viewer/nsViewerApp.h b/mozilla/webshell/tests/viewer/nsViewerApp.h index 3f8ecc5348a..1ddf059e116 100644 --- a/mozilla/webshell/tests/viewer/nsViewerApp.h +++ b/mozilla/webshell/tests/viewer/nsViewerApp.h @@ -80,6 +80,7 @@ public: protected: nsViewerApp(); + nsresult InitializeWindowCreator(); void Destroy(); nsresult AutoregisterComponents(); diff --git a/mozilla/webshell/tests/viewer/nsWebBrowserChrome.cpp b/mozilla/webshell/tests/viewer/nsWebBrowserChrome.cpp index 18c94bfade4..2b673cc3d05 100644 --- a/mozilla/webshell/tests/viewer/nsWebBrowserChrome.cpp +++ b/mozilla/webshell/tests/viewer/nsWebBrowserChrome.cpp @@ -90,7 +90,17 @@ NS_INTERFACE_MAP_END NS_IMETHODIMP nsWebBrowserChrome::GetInterface(const nsIID &aIID, void** aInstancePtr) { - return QueryInterface(aIID, aInstancePtr); + NS_ENSURE_ARG_POINTER(aInstancePtr); + + /* WindowCreator wants the main content shell when it asks a chrome window + for this interface. */ + if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) { + nsIDOMWindow *contentWin; + mBrowserWindow->mWebBrowser->GetContentDOMWindow(&contentWin); + *aInstancePtr = contentWin; + return NS_OK; + } + return QueryInterface(aIID, aInstancePtr); } //***************************************************************************** @@ -122,8 +132,11 @@ NS_IMETHODIMP nsWebBrowserChrome::SetWebBrowser(nsIWebBrowser* aWebBrowser) NS_IMETHODIMP nsWebBrowserChrome::GetWebBrowser(nsIWebBrowser** aWebBrowser) { - NS_ERROR("Haven't Implemented this yet"); - return NS_ERROR_FAILURE; + // Unimplemented, and probably will remain so; xpfe windows have docshells, + // not webbrowsers. Note that we're relying on this to differentiate + // embedded instances from Mozilla in nsWindowWatcher::InitializeDocshell. + // (Don't let me stop you, but keep that in mind.) + return NS_ERROR_FAILURE; } NS_IMETHODIMP nsWebBrowserChrome::SetChromeFlags(PRUint32 aChromeFlags) @@ -138,28 +151,6 @@ NS_IMETHODIMP nsWebBrowserChrome::GetChromeFlags(PRUint32* aChromeFlags) return NS_OK; } -NS_IMETHODIMP nsWebBrowserChrome::CreateBrowserWindow(PRUint32 aChromeMask, - PRInt32 aX, PRInt32 aY, PRInt32 aCX, PRInt32 aCY, nsIWebBrowser** aWebBrowser) -{ - if(mBrowserWindow->mWebCrawler && (mBrowserWindow->mWebCrawler->Crawling() || - mBrowserWindow->mWebCrawler->LoadingURLList())) - { - // Do not fly javascript popups when we are crawling - *aWebBrowser = nsnull; - return NS_ERROR_NOT_IMPLEMENTED; - } - - nsBrowserWindow* browser = nsnull; - mBrowserWindow->mApp->OpenWindow(aChromeMask, browser); - - NS_ENSURE_TRUE(browser, NS_ERROR_FAILURE); - browser->mWebBrowserChrome->SetChromeFlags(aChromeMask); - - *aWebBrowser = browser->mWebBrowser; - NS_IF_ADDREF(*aWebBrowser); - return NS_OK; -} - NS_IMETHODIMP nsWebBrowserChrome::DestroyBrowserWindow() { ExitModalEventLoop(NS_OK); @@ -678,7 +669,4 @@ void nsWebBrowserChrome::OnWindowActivityFinished() void nsWebBrowserChrome::EnableParent(PRBool aEnable) { - nsCOMPtr parentWidget = mBrowserWindow->mWindow; - if (parentWidget) - parentWidget->Enable(aEnable); } diff --git a/mozilla/webshell/tests/viewer/nsWindowCreator.cpp b/mozilla/webshell/tests/viewer/nsWindowCreator.cpp new file mode 100644 index 00000000000..54b634cf023 --- /dev/null +++ b/mozilla/webshell/tests/viewer/nsWindowCreator.cpp @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIWebBrowserChrome.h" +#include "nsBrowserWindow.h" +#include "nsViewerApp.h" +#include "nsWindowCreator.h" + +nsWindowCreator::nsWindowCreator(nsViewerApp *aApp) +{ + NS_INIT_REFCNT(); + mApp = aApp; +} + +nsWindowCreator::~nsWindowCreator() +{ +} + +NS_IMPL_ISUPPORTS1(nsWindowCreator, nsIWindowCreator) + +NS_IMETHODIMP +nsWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent, + PRUint32 aChromeMask, + nsIWebBrowserChrome **_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + *_retval = NULL; + +#if 0 + // XXX (copied from its original home in nsWebBrowserChrome. we need to + // ask this question of aParent and we don't have the interfaces. + // so I'm punting for now) + + // Do not fly javascript popups when we are crawling + if(mBrowserWindow->mWebCrawler && (mBrowserWindow->mWebCrawler->Crawling() || + mBrowserWindow->mWebCrawler->LoadingURLList())) { + + *aWebBrowser = nsnull; + return NS_ERROR_NOT_IMPLEMENTED; + } +#endif + + nsBrowserWindow* browser = nsnull; + mApp->OpenWindow(aChromeMask, browser); + NS_ENSURE_TRUE(browser, NS_ERROR_FAILURE); + + nsCOMPtr chrome(do_GetInterface(NS_STATIC_CAST(nsIInterfaceRequestor *, browser))); + if (chrome) { + chrome->SetChromeFlags(aChromeMask); + *_retval = chrome; + NS_ADDREF(*_retval); + } + + return NS_OK; +} + diff --git a/mozilla/webshell/tests/viewer/nsWindowCreator.h b/mozilla/webshell/tests/viewer/nsWindowCreator.h new file mode 100644 index 00000000000..f6c6d38ad1e --- /dev/null +++ b/mozilla/webshell/tests/viewer/nsWindowCreator.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __WindowCreator_h_ +#define __WindowCreator_h_ + +#include "nsIWindowCreator.h" + +class nsViewerApp; + +class nsWindowCreator : + public nsIWindowCreator +{ +public: + nsWindowCreator(nsViewerApp *aApp); + virtual ~nsWindowCreator(); + + NS_DECL_ISUPPORTS + NS_DECL_NSIWINDOWCREATOR + +private: + nsViewerApp *mApp; +}; + +#endif + diff --git a/mozilla/xpfe/appshell/public/nsIXULWindow.idl b/mozilla/xpfe/appshell/public/nsIXULWindow.idl index 3f84e713e3e..954920e8009 100644 --- a/mozilla/xpfe/appshell/public/nsIXULWindow.idl +++ b/mozilla/xpfe/appshell/public/nsIXULWindow.idl @@ -32,66 +32,75 @@ interface nsIDocShellTreeItem; [scriptable, uuid(D9CB00E0-CA39-11d3-B029-00A024FFC08C)] interface nsIXULWindow : nsISupports { - /* - The docshell owning the XUL for this window. - */ - readonly attribute nsIDocShell docShell; + /** + The docshell owning the XUL for this window. + */ + readonly attribute nsIDocShell docShell; - /* - Indicates if this window is instrinsically sized. - */ - attribute boolean intrinsicallySized; + /** + Indicates if this window is instrinsically sized. + */ + attribute boolean intrinsicallySized; - /* - This returns the primary content shell. - - Note that this is a docshell tree item and therefore can not be assured of - what object it is. It could be an editor, a docshell, or a browser object. - Or down the road any other object that supports being a DocShellTreeItem - Query accordingly to determine the capabilities. - */ - readonly attribute nsIDocShellTreeItem primaryContentShell; + /** + This returns the primary content shell. + + Note that this is a docshell tree item and therefore can not be assured of + what object it is. It could be an editor, a docshell, or a browser object. + Or down the road any other object that supports being a DocShellTreeItem + Query accordingly to determine the capabilities. + */ + readonly attribute nsIDocShellTreeItem primaryContentShell; - /* - This returns the content shell specified by the supplied id. - - Note that this is a docshell tree item and therefore can not be assured of - what object it is. It could be an editor, a docshell, or a browser object. - Or down the road any other object that supports being a DocShellTreeItem - Query accordingly to determine the capabilities. - */ - nsIDocShellTreeItem getContentShellById(in wstring ID); + /** + This returns the content shell specified by the supplied id. + + Note that this is a docshell tree item and therefore can not be assured of + what object it is. It could be an editor, a docshell, or a browser object. + Or down the road any other object that supports being a DocShellTreeItem + Query accordingly to determine the capabilities. + */ + nsIDocShellTreeItem getContentShellById(in wstring ID); - /* - Tell this window that it has picked up or lost a child XUL window - */ - void AddChildWindow(in nsIXULWindow aChild); - void RemoveChildWindow(in nsIXULWindow aChild); + /** + Tell this window that it has picked up or lost a child XUL window + @param aChild the child window being added or removed + */ + void addChildWindow(in nsIXULWindow aChild); + void removeChildWindow(in nsIXULWindow aChild); - /* - Move the window to a centered position. - @param aRelative the window relative to which the window is moved. - See screen parameter for details. if null, the - window is centered relative to the main screen. - @param aScreen PR_TRUE to center the window relative to the screen - containing aRelative. PR_FALSE to center it relative - to aRelative itself. - @param aAlert PR_TRUE to move the window to an alert position, - generally centered horizontally and 1/3 down from the top. - */ - void center(in nsIXULWindow aRelative, in boolean aScreen, in boolean aAlert); + /** + Move the window to a centered position. + @param aRelative the window relative to which the window is moved. + See screen parameter for details. if null, the + window is centered relative to the main screen. + @param aScreen PR_TRUE to center the window relative to the screen + containing aRelative. PR_FALSE to center it relative + to aRelative itself. + @param aAlert PR_TRUE to move the window to an alert position, + generally centered horizontally and 1/3 down from the top. + */ + void center(in nsIXULWindow aRelative, in boolean aScreen, in boolean aAlert); - /* - Shows the window as a modal window - */ - void showModal(); + /** + Shows the window as a modal window. That is, ensures that it is visible + and runs a local event loop, exiting only once the window has been closed. + */ + void showModal(); - const unsigned long lowestZ = 0; - const unsigned long loweredZ = 4; /* "alwaysLowered" attribute */ - const unsigned long normalZ = 5; - const unsigned long raisedZ = 6; /* "alwaysRaised" attribute */ - const unsigned long highestZ = 9; + const unsigned long lowestZ = 0; + const unsigned long loweredZ = 4; /* "alwaysLowered" attribute */ + const unsigned long normalZ = 5; + const unsigned long raisedZ = 6; /* "alwaysRaised" attribute */ + const unsigned long highestZ = 9; - readonly attribute unsigned long zlevel; + readonly attribute unsigned long zlevel; + + /** + Create a new window. + @param aChromeFlags: see nsIWebBrowserChrome + @return the newly minted window + */ + nsIXULWindow createNewWindow(in PRInt32 aChromeFlags); }; diff --git a/mozilla/xpfe/appshell/src/nsChromeTreeOwner.cpp b/mozilla/xpfe/appshell/src/nsChromeTreeOwner.cpp index 3b7e030ab6a..42b10f5c01f 100644 --- a/mozilla/xpfe/appshell/src/nsChromeTreeOwner.cpp +++ b/mozilla/xpfe/appshell/src/nsChromeTreeOwner.cpp @@ -82,6 +82,8 @@ NS_IMETHODIMP nsChromeTreeOwner::GetInterface(const nsIID& aIID, void** aSink) return mXULWindow->GetInterface(aIID, aSink); if(aIID.Equals(NS_GET_IID(nsIWebBrowserChrome))) return mXULWindow->GetInterface(aIID, aSink); + if (aIID.Equals(NS_GET_IID(nsIXULWindow))) + return mXULWindow->QueryInterface(aIID, aSink); return QueryInterface(aIID, aSink); } @@ -181,12 +183,6 @@ NS_IMETHODIMP nsChromeTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem, return mXULWindow->SizeShellTo(aShellItem, aCX, aCY); } -NS_IMETHODIMP nsChromeTreeOwner::GetNewWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem) -{ - return mXULWindow->GetNewWindow(aChromeFlags, aDocShellTreeItem); -} - NS_IMETHODIMP nsChromeTreeOwner::SetPersistence(PRBool aPersistPosition, PRBool aPersistSize, diff --git a/mozilla/xpfe/appshell/src/nsContentTreeOwner.cpp b/mozilla/xpfe/appshell/src/nsContentTreeOwner.cpp index b07a5ad22af..54c04c770c9 100644 --- a/mozilla/xpfe/appshell/src/nsContentTreeOwner.cpp +++ b/mozilla/xpfe/appshell/src/nsContentTreeOwner.cpp @@ -116,6 +116,9 @@ NS_IMETHODIMP nsContentTreeOwner::GetInterface(const nsIID& aIID, void** aSink) return NS_ERROR_FAILURE; } + if (aIID.Equals(NS_GET_IID(nsIXULWindow))) + return mXULWindow->QueryInterface(aIID, aSink); + return QueryInterface(aIID, aSink); } @@ -210,12 +213,6 @@ NS_IMETHODIMP nsContentTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem, return mXULWindow->SizeShellTo(aShellItem, aCX, aCY); } -NS_IMETHODIMP nsContentTreeOwner::GetNewWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem) -{ - return mXULWindow->GetNewWindow(aChromeFlags, aDocShellTreeItem); -} - NS_IMETHODIMP nsContentTreeOwner::SetPersistence(PRBool aPersistPosition, PRBool aPersistSize, @@ -370,8 +367,11 @@ NS_IMETHODIMP nsContentTreeOwner::SetWebBrowser(nsIWebBrowser* aWebBrowser) NS_IMETHODIMP nsContentTreeOwner::GetWebBrowser(nsIWebBrowser** aWebBrowser) { - NS_ERROR("Haven't Implemented this yet"); - return NS_ERROR_FAILURE; + // Unimplemented, and probably will remain so; xpfe windows have docshells, + // not webbrowsers. Note that we're relying on this to differentiate + // embedded instances from Mozilla in nsWindowWatcher::InitializeDocshell. + // (Don't let me stop you, but keep that in mind.) + return NS_ERROR_FAILURE; } NS_IMETHODIMP nsContentTreeOwner::SetChromeFlags(PRUint32 aChromeFlags) @@ -390,13 +390,6 @@ NS_IMETHODIMP nsContentTreeOwner::GetChromeFlags(PRUint32* aChromeFlags) return NS_OK; } -NS_IMETHODIMP nsContentTreeOwner::CreateBrowserWindow(PRUint32 aChromeFlags, - PRInt32 aX, PRInt32 aY, PRInt32 aCX, PRInt32 aCY, nsIWebBrowser** aWebBrowser) -{ - NS_ERROR("Haven't Implemented this yet"); - return NS_ERROR_FAILURE; -} - NS_IMETHODIMP nsContentTreeOwner::DestroyBrowserWindow() { NS_ERROR("Haven't Implemented this yet"); diff --git a/mozilla/xpfe/appshell/src/nsXULWindow.cpp b/mozilla/xpfe/appshell/src/nsXULWindow.cpp index bcb92852b72..6ae26ce09c2 100644 --- a/mozilla/xpfe/appshell/src/nsXULWindow.cpp +++ b/mozilla/xpfe/appshell/src/nsXULWindow.cpp @@ -1258,21 +1258,19 @@ NS_IMETHODIMP nsXULWindow::ExitModalLoop(nsresult aStatus) return NS_OK; } -NS_IMETHODIMP nsXULWindow::GetNewWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem) +// top-level function to create a new window +NS_IMETHODIMP nsXULWindow::CreateNewWindow(PRInt32 aChromeFlags, + nsIXULWindow **_retval) { - NS_ENSURE_ARG_POINTER(aDocShellTreeItem); + NS_ENSURE_ARG_POINTER(_retval); - if(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) - return CreateNewChromeWindow(aChromeFlags, aDocShellTreeItem); - else - return CreateNewContentWindow(aChromeFlags, aDocShellTreeItem); - - return NS_ERROR_FAILURE; + if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) + return CreateNewChromeWindow(aChromeFlags, _retval); + return CreateNewContentWindow(aChromeFlags, _retval); } NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem) + nsIXULWindow **_retval) { NS_TIMELINE_ENTER("nsXULWindow::CreateNewChromeWindow"); nsCOMPtr appShell(do_GetService(kAppShellServiceCID)); @@ -1296,16 +1294,15 @@ NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(PRInt32 aChromeFlags, if(browserChrome) browserChrome->SetChromeFlags(aChromeFlags); - nsCOMPtr docShell; - newWindow->GetDocShell(getter_AddRefs(docShell)); - CallQueryInterface(docShell, aDocShellTreeItem); - + *_retval = newWindow; + NS_ADDREF(*_retval); + NS_TIMELINE_LEAVE("nsXULWindow::CreateNewChromeWindow done"); return NS_OK; } NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem) + nsIXULWindow **_retval) { NS_TIMELINE_ENTER("nsXULWindow::CreateNewContentWindow"); nsCOMPtr appShell(do_GetService(kAppShellServiceCID)); @@ -1398,11 +1395,9 @@ NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(PRInt32 aChromeFlags, subShell->Spindown(); - // We're out of the nested loop. - // During the layout of the new window, all content shells were located and placed - // into the new window's content shell array. Locate the "content area" content - // shell. - newWindow->GetPrimaryContentShell(aDocShellTreeItem); + *_retval = newWindow; + NS_ADDREF(*_retval); + NS_TIMELINE_LEAVE("nsXULWindow::CreateNewContentWindow"); return NS_OK; } @@ -1426,7 +1421,7 @@ NS_IMETHODIMP nsXULWindow::NotifyObservers(const PRUnichar* aTopic, nsCAutoString topic; topic.Assign(prefix); topic.Append(";"); topic.AppendWithConversion(aTopic); - + NS_ENSURE_SUCCESS(service->NotifyObservers(removeme, topic.get(), aData), NS_ERROR_FAILURE); return NS_OK; diff --git a/mozilla/xpfe/appshell/src/nsXULWindow.h b/mozilla/xpfe/appshell/src/nsXULWindow.h index 19b52720836..5dbfa2bd95f 100644 --- a/mozilla/xpfe/appshell/src/nsXULWindow.h +++ b/mozilla/xpfe/appshell/src/nsXULWindow.h @@ -89,12 +89,10 @@ protected: NS_IMETHOD SizeShellTo(nsIDocShellTreeItem* aShellItem, PRInt32 aCX, PRInt32 aCY); NS_IMETHOD ExitModalLoop(nsresult aStatus); - NS_IMETHOD GetNewWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem); NS_IMETHOD CreateNewChromeWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem); + nsIXULWindow **_retval); NS_IMETHOD CreateNewContentWindow(PRInt32 aChromeFlags, - nsIDocShellTreeItem** aDocShellTreeItem); + nsIXULWindow **_retval); NS_IMETHOD NotifyObservers(const PRUnichar* aTopic, const PRUnichar* aData); void EnableParent(PRBool aEnable); diff --git a/mozilla/xpfe/bootstrap/Makefile.in b/mozilla/xpfe/bootstrap/Makefile.in index 3dcfc439237..e5a94159d51 100644 --- a/mozilla/xpfe/bootstrap/Makefile.in +++ b/mozilla/xpfe/bootstrap/Makefile.in @@ -30,6 +30,7 @@ include $(topsrcdir)/config/config.mk MODULE = apprunner REQUIRES = xpcom \ + xpconnect \ string \ webbrwsr \ widget \ @@ -57,7 +58,6 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),os2) REQUIRES += \ intl \ profile \ - xpconnect \ $(NULL) endif diff --git a/mozilla/xpfe/bootstrap/nsWindowCreator.cpp b/mozilla/xpfe/bootstrap/nsWindowCreator.cpp index c58eff16b1e..c704c967d36 100644 --- a/mozilla/xpfe/bootstrap/nsWindowCreator.cpp +++ b/mozilla/xpfe/bootstrap/nsWindowCreator.cpp @@ -66,15 +66,21 @@ #include "nsCOMPtr.h" #include "nsAppShellCIDs.h" +#include "nsWidgetsCID.h" +#include "nsWindowCreator.h" + +#include "nsIAppShell.h" #include "nsIAppShellService.h" +#include "nsIDocShellTreeItem.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" +#include "nsIJSContextStack.h" #include "nsIServiceManager.h" #include "nsIXULWindow.h" #include "nsIWebBrowserChrome.h" -#include "nsWindowCreator.h" static NS_DEFINE_CID(kAppShellServiceCID, NS_APPSHELL_SERVICE_CID); +static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); nsWindowCreator::nsWindowCreator() { NS_INIT_REFCNT(); @@ -93,31 +99,33 @@ nsWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent, NS_ENSURE_ARG_POINTER(_retval); *_retval = 0; - /* There is no valid way to get from an nsIWebBrowserChrome interface - to the corresponding nsXULWindow, so we can't really service a request - to make a window with a parent. This shouldn't be a problem, since - convention suggests this method only be used when there is no parent - window (otherwise, just call Open() on the parent). However, we - should say something, just to be sure: */ - NS_ASSERTION(!aParent, "window creator reached with non-null parent"); - if (aParent) - return NS_ERROR_INVALID_ARG; - - /* And you really shouldn't be making dependent windows without a parent. - But unparented modal (and therefore dependent) windows happen - in our codebase, so we allow it after some bellyaching: */ - if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT) - NS_WARNING("dependent window created without a parent"); - - nsCOMPtr appShell(do_GetService(kAppShellServiceCID)); - if (!appShell) - return NS_ERROR_FAILURE; - nsCOMPtr newWindow; - appShell->CreateTopLevelWindow(0, 0, PR_FALSE, PR_FALSE, - aChromeFlags, nsIAppShellService::SIZE_TO_CONTENT, - nsIAppShellService::SIZE_TO_CONTENT, getter_AddRefs(newWindow)); + if (aParent) { + nsCOMPtr xulParent(do_GetInterface(aParent)); + NS_ASSERTION(xulParent, "window created using non-XUL parent. that's unexpected, but may work."); + if (xulParent) + xulParent->CreateNewWindow(aChromeFlags, getter_AddRefs(newWindow)); + } + + // no parent or incompetent parent. try again using basic methods: + if (!newWindow) { + /* You really shouldn't be making dependent windows without a parent. + But unparented modal (and therefore dependent) windows happen + in our codebase, so we allow it after some bellyaching: */ + if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT) + NS_WARNING("dependent window created without a parent"); + + nsCOMPtr appShell(do_GetService(kAppShellServiceCID)); + if (!appShell) + return NS_ERROR_FAILURE; + + appShell->CreateTopLevelWindow(0, 0, PR_FALSE, PR_FALSE, + aChromeFlags, nsIAppShellService::SIZE_TO_CONTENT, + nsIAppShellService::SIZE_TO_CONTENT, getter_AddRefs(newWindow)); + } + + // if anybody gave us anything to work with, use it nsCOMPtr thing(do_QueryInterface(newWindow)); if (thing) thing->GetInterface(NS_GET_IID(nsIWebBrowserChrome), (void **) _retval);