From 8697a1814f3ea956f8c1cf102af55e1c75352484 Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Thu, 5 Jun 2014 22:51:14 -0400 Subject: [PATCH] Bug 1021466 - Part 2: Make it possible to pass in an nsITabParent when opening windows, and then stash that nsITabParent in the newly created chrome docshell. r=smaug. --- dom/base/nsGlobalWindow.cpp | 4 ++-- embedding/base/nsIWindowCreator2.idl | 6 ++++- .../public/nsPIWindowWatcher.idl | 9 ++++++-- .../windowwatcher/src/nsWindowWatcher.cpp | 8 ++++--- .../windowwatcher/src/nsWindowWatcher.h | 2 ++ toolkit/components/startup/nsAppStartup.cpp | 8 ++++--- widget/tests/TestAppShellSteadyState.cpp | 2 +- xpfe/appshell/public/nsIAppShellService.idl | 9 +++++--- xpfe/appshell/public/nsIXULWindow.idl | 8 +++++-- xpfe/appshell/src/nsAppShellService.cpp | 12 +++++----- xpfe/appshell/src/nsAppShellService.h | 4 +++- xpfe/appshell/src/nsWebShellWindow.cpp | 3 +++ xpfe/appshell/src/nsWebShellWindow.h | 2 ++ xpfe/appshell/src/nsXULWindow.cpp | 22 +++++++++++++++---- xpfe/appshell/src/nsXULWindow.h | 5 +++-- 15 files changed, 75 insertions(+), 29 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 5ddbc1ca9bef..cee3cc3dd6c0 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -11644,7 +11644,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName, // !aCalledNoScript. rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr, /* aCalledFromScript = */ true, - aDialog, aNavigate, argv, + aDialog, aNavigate, nullptr, argv, getter_AddRefs(domReturn)); } else { // Force a system caller here so that the window watcher won't screw us @@ -11664,7 +11664,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName, rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr, /* aCalledFromScript = */ false, - aDialog, aNavigate, aExtraArgument, + aDialog, aNavigate, nullptr, aExtraArgument, getter_AddRefs(domReturn)); } diff --git a/embedding/base/nsIWindowCreator2.idl b/embedding/base/nsIWindowCreator2.idl index 7a97fab1f31e..41ac77e46e97 100644 --- a/embedding/base/nsIWindowCreator2.idl +++ b/embedding/base/nsIWindowCreator2.idl @@ -17,10 +17,11 @@ #include "nsIWindowCreator.idl" +interface nsITabParent; interface nsIURI; interface nsIWebBrowserChrome; -[scriptable, uuid(f673ec81-a4b0-11d6-964b-eb5a2bf216fc)] +[scriptable, uuid(e28f810b-9b49-4927-a4be-62a74fadfe21)] interface nsIWindowCreator2 : nsIWindowCreator { @@ -44,6 +45,8 @@ interface nsIWindowCreator2 : nsIWindowCreator { may use the URL to help determine what sort of window to open or whether to cancel window creation. It will not load the URL. + @param aOpeningTab The TabParent that is trying to open this new chrome + window. Can be nullptr. @param cancel Return |true| to reject window creation. If true the implementation has determined the window should not be created at all. The caller should not default @@ -54,5 +57,6 @@ interface nsIWindowCreator2 : nsIWindowCreator { in uint32_t chromeFlags, in uint32_t contextFlags, in nsIURI uri, + in nsITabParent aOpeningTab, out boolean cancel); }; diff --git a/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl b/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl index 7581595c17c9..a552567e84ba 100644 --- a/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl +++ b/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl @@ -15,8 +15,9 @@ interface nsISimpleEnumerator; interface nsIWebBrowserChrome; interface nsIDocShellTreeItem; interface nsIArray; +interface nsITabParent; -[uuid(00788A84-152F-4BD8-A814-FD8EB545DB29)] +[uuid(0f2d9d75-c46b-4114-802e-83b4655e61d2)] interface nsPIWindowWatcher : nsISupports { @@ -51,6 +52,9 @@ interface nsPIWindowWatcher : nsISupports @param aDialog use dialog defaults (see nsIDOMWindow::openDialog) @param aNavigate true if we should navigate the new window to the specified URL. + @param aOpeningTab the nsITabParent that is opening the new window. The + nsITabParent is a remote tab belonging to aParent. Can + be nullptr if this window is not being opened from a tab. @param aArgs Window argument @return the new window @@ -65,7 +69,8 @@ interface nsPIWindowWatcher : nsISupports nsIDOMWindow openWindow2(in nsIDOMWindow aParent, in string aUrl, in string aName, in string aFeatures, in boolean aCalledFromScript, in boolean aDialog, - in boolean aNavigate, in nsISupports aArgs); + in boolean aNavigate, in nsITabParent aOpeningTab, + in nsISupports aArgs); /** * Find a named docshell tree item amongst all windows registered diff --git a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp index 122d60d3bbdb..6c7a61705c73 100644 --- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp @@ -342,7 +342,7 @@ nsWindowWatcher::OpenWindow(nsIDOMWindow *aParent, return OpenWindowInternal(aParent, aUrl, aName, aFeatures, /* calledFromJS = */ false, dialog, - /* navigate = */ true, argv, _retval); + /* navigate = */ true, nullptr, argv, _retval); } struct SizeSpec { @@ -394,6 +394,7 @@ nsWindowWatcher::OpenWindow2(nsIDOMWindow *aParent, bool aCalledFromScript, bool aDialog, bool aNavigate, + nsITabParent *aOpeningTab, nsISupports *aArguments, nsIDOMWindow **_retval) { @@ -414,7 +415,7 @@ nsWindowWatcher::OpenWindow2(nsIDOMWindow *aParent, return OpenWindowInternal(aParent, aUrl, aName, aFeatures, aCalledFromScript, dialog, - aNavigate, argv, _retval); + aNavigate, aOpeningTab, argv, _retval); } nsresult @@ -425,6 +426,7 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow *aParent, bool aCalledFromJS, bool aDialog, bool aNavigate, + nsITabParent *aOpeningTab, nsIArray *argv, nsIDOMWindow **_retval) { @@ -698,7 +700,7 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow *aParent, bool cancel = false; rv = windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags, contextFlags, uriToLoad, - &cancel, + aOpeningTab, &cancel, getter_AddRefs(newChrome)); if (NS_SUCCEEDED(rv) && cancel) { newChrome = 0; // just in case diff --git a/embedding/components/windowwatcher/src/nsWindowWatcher.h b/embedding/components/windowwatcher/src/nsWindowWatcher.h index 7cb324411daa..c3e90a06238e 100644 --- a/embedding/components/windowwatcher/src/nsWindowWatcher.h +++ b/embedding/components/windowwatcher/src/nsWindowWatcher.h @@ -15,6 +15,7 @@ #include "nsIWindowCreator.h" // for stupid compilers #include "nsIWindowWatcher.h" #include "nsIPromptFactory.h" +#include "nsITabParent.h" #include "nsPIWindowWatcher.h" #include "nsTArray.h" #include "js/TypeDecls.h" @@ -77,6 +78,7 @@ protected: bool aCalledFromJS, bool aDialog, bool aNavigate, + nsITabParent *aOpeningTab, nsIArray *argv, nsIDOMWindow **_retval); diff --git a/toolkit/components/startup/nsAppStartup.cpp b/toolkit/components/startup/nsAppStartup.cpp index 7e8e332b1e04..f1de711466a6 100644 --- a/toolkit/components/startup/nsAppStartup.cpp +++ b/toolkit/components/startup/nsAppStartup.cpp @@ -612,7 +612,7 @@ nsAppStartup::CreateChromeWindow(nsIWebBrowserChrome *aParent, nsIWebBrowserChrome **_retval) { bool cancel; - return CreateChromeWindow2(aParent, aChromeFlags, 0, 0, &cancel, _retval); + return CreateChromeWindow2(aParent, aChromeFlags, 0, 0, nullptr, &cancel, _retval); } @@ -625,6 +625,7 @@ nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent, uint32_t aChromeFlags, uint32_t aContextFlags, nsIURI *aURI, + nsITabParent *aOpeningTab, bool *aCancel, nsIWebBrowserChrome **_retval) { @@ -644,7 +645,7 @@ nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent, NS_ASSERTION(xulParent, "window created using non-XUL parent. that's unexpected, but may work."); if (xulParent) - xulParent->CreateNewWindow(aChromeFlags, getter_AddRefs(newWindow)); + xulParent->CreateNewWindow(aChromeFlags, aOpeningTab, getter_AddRefs(newWindow)); // And if it fails, don't try again without a parent. It could fail // intentionally (bug 115969). } else { // try using basic methods: @@ -657,10 +658,11 @@ nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent, nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); if (!appShell) return NS_ERROR_FAILURE; - + appShell->CreateTopLevelWindow(0, 0, aChromeFlags, nsIAppShellService::SIZE_TO_CONTENT, nsIAppShellService::SIZE_TO_CONTENT, + aOpeningTab, getter_AddRefs(newWindow)); } diff --git a/widget/tests/TestAppShellSteadyState.cpp b/widget/tests/TestAppShellSteadyState.cpp index abf952a082a0..16f6500bfc9e 100644 --- a/widget/tests/TestAppShellSteadyState.cpp +++ b/widget/tests/TestAppShellSteadyState.cpp @@ -407,7 +407,7 @@ Test4Internal(nsIAppShell* aAppShell) uint32_t flags = nsIWebBrowserChrome::CHROME_DEFAULT; nsCOMPtr xulWindow; - if (NS_FAILED(appService->CreateTopLevelWindow(nullptr, uri, flags, 100, 100, + if (NS_FAILED(appService->CreateTopLevelWindow(nullptr, uri, flags, 100, 100, nullptr, getter_AddRefs(xulWindow)))) { fail("Failed to create new window"); return false; diff --git a/xpfe/appshell/public/nsIAppShellService.idl b/xpfe/appshell/public/nsIAppShellService.idl index af19e2a6ec76..1b20c9d000ac 100644 --- a/xpfe/appshell/public/nsIAppShellService.idl +++ b/xpfe/appshell/public/nsIAppShellService.idl @@ -10,6 +10,7 @@ interface nsIWebNavigation; interface nsIURI; interface nsIDOMWindow; interface nsIAppShell; +interface nsITabParent; [ptr] native JSContext(JSContext); @@ -17,7 +18,7 @@ interface nsIAppShell; #include "js/TypeDecls.h" %} -[scriptable, uuid(2fa2f813-c216-4efb-8a8c-de60108ce5e5)] +[scriptable, uuid(41a2f0c6-3ca1-44f9-8efa-744a43aa399d)] interface nsIAppShellService : nsISupports { /** @@ -35,14 +36,16 @@ interface nsIAppShellService : nsISupports * tag in the XUL. Set to NS_SIZETOCONTENT to force * the window to wrap to its contents. * @param aInitialHeight like aInitialWidth, but subtly different. - * @param aResult the newly created window is returned here. + * @param aOpeningTab The TabParent that requested that this window be opened. + * Can be left null. */ const long SIZE_TO_CONTENT = -1; nsIXULWindow createTopLevelWindow(in nsIXULWindow aParent, in nsIURI aUrl, in uint32_t aChromeMask, in long aInitialWidth, - in long aInitialHeight); + in long aInitialHeight, + in nsITabParent aOpeningTab); /** * This is the constructor for creating an invisible DocShell. diff --git a/xpfe/appshell/public/nsIXULWindow.idl b/xpfe/appshell/public/nsIXULWindow.idl index 63b5617a7cad..72939252c940 100644 --- a/xpfe/appshell/public/nsIXULWindow.idl +++ b/xpfe/appshell/public/nsIXULWindow.idl @@ -16,8 +16,9 @@ interface nsIDocShell; interface nsIDocShellTreeItem; interface nsIXULBrowserWindow; +interface nsITabParent; -[scriptable, uuid(CCF9E98A-E442-4061-9F74-94539DD9FE9E)] +[scriptable, uuid(a68a40b9-f7df-47ff-a874-2af3df7eb888)] interface nsIXULWindow : nsISupports { /** @@ -108,9 +109,12 @@ interface nsIXULWindow : nsISupports /** * Create a new window. * @param aChromeFlags see nsIWebBrowserChrome + * @param aOpeningTab the TabParent that requested this new window be opened. + * Can be left null. * @return the newly minted window */ - nsIXULWindow createNewWindow(in int32_t aChromeFlags); + nsIXULWindow createNewWindow(in int32_t aChromeFlags, + in nsITabParent aOpeningTab); attribute nsIXULBrowserWindow XULBrowserWindow; diff --git a/xpfe/appshell/src/nsAppShellService.cpp b/xpfe/appshell/src/nsAppShellService.cpp index df0e37e45c25..0b54acf63f2e 100644 --- a/xpfe/appshell/src/nsAppShellService.cpp +++ b/xpfe/appshell/src/nsAppShellService.cpp @@ -127,7 +127,7 @@ nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate) if (!aIsPrivate) { rv = JustCreateTopWindow(nullptr, url, chromeMask, initialWidth, initialHeight, - true, getter_AddRefs(newWindow)); + true, nullptr, getter_AddRefs(newWindow)); NS_ENSURE_SUCCESS(rv, rv); mHiddenWindow.swap(newWindow); @@ -137,7 +137,7 @@ nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate) rv = JustCreateTopWindow(nullptr, url, chromeMask, initialWidth, initialHeight, - true, getter_AddRefs(newWindow)); + true, nullptr, getter_AddRefs(newWindow)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr docShell; @@ -181,6 +181,7 @@ nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent, uint32_t aChromeMask, int32_t aInitialWidth, int32_t aInitialHeight, + nsITabParent *aOpeningTab, nsIXULWindow **aResult) { @@ -191,7 +192,7 @@ nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent, nsWebShellWindow *newWindow = nullptr; rv = JustCreateTopWindow(aParent, aUrl, aChromeMask, aInitialWidth, aInitialHeight, - false, &newWindow); // addrefs + false, aOpeningTab, &newWindow); // addrefs *aResult = newWindow; // transfer ref @@ -482,11 +483,12 @@ CheckForFullscreenWindow() */ nsresult nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent, - nsIURI *aUrl, + nsIURI *aUrl, uint32_t aChromeMask, int32_t aInitialWidth, int32_t aInitialHeight, bool aIsHiddenWindow, + nsITabParent *aOpeningTab, nsWebShellWindow **aResult) { *aResult = nullptr; @@ -597,7 +599,7 @@ nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent, nsresult rv = window->Initialize(parent, center ? aParent : nullptr, aUrl, aInitialWidth, aInitialHeight, - aIsHiddenWindow, widgetInitData); + aIsHiddenWindow, aOpeningTab, widgetInitData); NS_ENSURE_SUCCESS(rv, rv); diff --git a/xpfe/appshell/src/nsAppShellService.h b/xpfe/appshell/src/nsAppShellService.h index 6523ed9343c7..20069bd38cdb 100644 --- a/xpfe/appshell/src/nsAppShellService.h +++ b/xpfe/appshell/src/nsAppShellService.h @@ -13,6 +13,7 @@ #include "nsWebShellWindow.h" #include "nsStringFwd.h" #include "nsAutoPtr.h" +#include "nsITabParent.h" #include "mozilla/Attributes.h" // {0099907D-123C-4853-A46A-43098B5FB68C} @@ -36,10 +37,11 @@ protected: void EnsurePrivateHiddenWindow(); nsresult JustCreateTopWindow(nsIXULWindow *aParent, - nsIURI *aUrl, + nsIURI *aUrl, uint32_t aChromeMask, int32_t aInitialWidth, int32_t aInitialHeight, bool aIsHiddenWindow, + nsITabParent *aOpeningTab, nsWebShellWindow **aResult); uint32_t CalculateWindowZLevel(nsIXULWindow *aParent, uint32_t aChromeMask); diff --git a/xpfe/appshell/src/nsWebShellWindow.cpp b/xpfe/appshell/src/nsWebShellWindow.cpp index cbfb8dd502bb..4fde3ac207b0 100644 --- a/xpfe/appshell/src/nsWebShellWindow.cpp +++ b/xpfe/appshell/src/nsWebShellWindow.cpp @@ -111,6 +111,7 @@ nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent, int32_t aInitialWidth, int32_t aInitialHeight, bool aIsHiddenWindow, + nsITabParent *aOpeningTab, nsWidgetInitData& widgetInitData) { nsresult rv; @@ -183,6 +184,8 @@ nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent, mDocShell = do_CreateInstance("@mozilla.org/docshell;1"); NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + mDocShell->SetOpener(aOpeningTab); + // Make sure to set the item type on the docshell _before_ calling // Create() so it knows what type it is. nsCOMPtr docShellAsItem(do_QueryInterface(mDocShell)); diff --git a/xpfe/appshell/src/nsWebShellWindow.h b/xpfe/appshell/src/nsWebShellWindow.h index 88281bb96bab..3f9d06d95c5e 100644 --- a/xpfe/appshell/src/nsWebShellWindow.h +++ b/xpfe/appshell/src/nsWebShellWindow.h @@ -12,6 +12,7 @@ #include "nsCOMPtr.h" #include "nsXULWindow.h" #include "nsIWidgetListener.h" +#include "nsITabParent.h" /* Forward declarations.... */ class nsIURI; @@ -37,6 +38,7 @@ public: nsIURI* aUrl, int32_t aInitialWidth, int32_t aInitialHeight, bool aIsHiddenWindow, + nsITabParent *aOpeningTab, nsWidgetInitData& widgetInitData); nsresult Toolbar(); diff --git a/xpfe/appshell/src/nsXULWindow.cpp b/xpfe/appshell/src/nsXULWindow.cpp index 200ac8c8d143..2e8542c9a338 100644 --- a/xpfe/appshell/src/nsXULWindow.cpp +++ b/xpfe/appshell/src/nsXULWindow.cpp @@ -1714,16 +1714,18 @@ NS_IMETHODIMP nsXULWindow::ExitModalLoop(nsresult aStatus) // top-level function to create a new window NS_IMETHODIMP nsXULWindow::CreateNewWindow(int32_t aChromeFlags, - nsIXULWindow **_retval) + nsITabParent *aOpeningTab, + nsIXULWindow **_retval) { NS_ENSURE_ARG_POINTER(_retval); if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) - return CreateNewChromeWindow(aChromeFlags, _retval); - return CreateNewContentWindow(aChromeFlags, _retval); + return CreateNewChromeWindow(aChromeFlags, aOpeningTab, _retval); + return CreateNewContentWindow(aChromeFlags, aOpeningTab, _retval); } NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags, + nsITabParent *aOpeningTab, nsIXULWindow **_retval) { nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); @@ -1735,6 +1737,7 @@ NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags, appShell->CreateTopLevelWindow(this, nullptr, aChromeFlags, nsIAppShellService::SIZE_TO_CONTENT, nsIAppShellService::SIZE_TO_CONTENT, + aOpeningTab, getter_AddRefs(newWindow)); NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); @@ -1746,6 +1749,7 @@ NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags, } NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags, + nsITabParent *aOpeningTab, nsIXULWindow **_retval) { nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); @@ -1778,6 +1782,7 @@ NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags, AutoNoJSAPI nojsapi; appShell->CreateTopLevelWindow(this, uri, aChromeFlags, 615, 480, + aOpeningTab, getter_AddRefs(newWindow)); NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE); } @@ -1798,7 +1803,16 @@ NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags, } } - NS_ENSURE_STATE(xulWin->mPrimaryContentShell); + // If aOpeningTab is not null, it means that we're creating a new window + // with a remote browser, which doesn't have a primary docshell. In that + // case, we check for the chrome window docshell and make sure that a new + // remote tab was opened and stashed in that docshell. + if (aOpeningTab) { + NS_ENSURE_STATE(xulWin->mDocShell); + NS_ENSURE_STATE(xulWin->mDocShell->GetOpenedRemote()); + } else { + NS_ENSURE_STATE(xulWin->mPrimaryContentShell); + } *_retval = newWindow; NS_ADDREF(*_retval); diff --git a/xpfe/appshell/src/nsXULWindow.h b/xpfe/appshell/src/nsXULWindow.h index 9bfbbe6d2082..acd17f0245f2 100644 --- a/xpfe/appshell/src/nsXULWindow.h +++ b/xpfe/appshell/src/nsXULWindow.h @@ -32,6 +32,7 @@ #include "nsIXULBrowserWindow.h" #include "nsIWeakReference.h" #include "nsIWidgetListener.h" +#include "nsITabParent.h" namespace mozilla { namespace dom { @@ -108,8 +109,8 @@ protected: NS_IMETHOD SizeShellTo(nsIDocShellTreeItem* aShellItem, int32_t aCX, int32_t aCY); NS_IMETHOD ExitModalLoop(nsresult aStatus); - NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, nsIXULWindow **_retval); - NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, nsIXULWindow **_retval); + NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval); + NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval); void EnableParent(bool aEnable); bool ConstrainToZLevel(bool aImmediate, nsWindowZ *aPlacement,