From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- xpfe/appshell/moz.build | 42 + xpfe/appshell/nsAppShellCID.h | 10 + xpfe/appshell/nsAppShellFactory.cpp | 56 + xpfe/appshell/nsAppShellService.cpp | 1001 ++++++++++ xpfe/appshell/nsAppShellService.h | 58 + xpfe/appshell/nsAppShellWindowEnumerator.cpp | 495 +++++ xpfe/appshell/nsAppShellWindowEnumerator.h | 166 ++ xpfe/appshell/nsChromeTreeOwner.cpp | 561 ++++++ xpfe/appshell/nsChromeTreeOwner.h | 53 + xpfe/appshell/nsContentTreeOwner.cpp | 1131 +++++++++++ xpfe/appshell/nsContentTreeOwner.h | 63 + xpfe/appshell/nsIAppShellService.idl | 150 ++ xpfe/appshell/nsIPopupWindowManager.idl | 35 + xpfe/appshell/nsIWindowMediator.idl | 206 ++ xpfe/appshell/nsIWindowMediatorListener.idl | 19 + xpfe/appshell/nsIWindowlessBrowser.idl | 27 + xpfe/appshell/nsIXULBrowserWindow.idl | 78 + xpfe/appshell/nsIXULWindow.idl | 168 ++ xpfe/appshell/nsWebShellWindow.cpp | 911 +++++++++ xpfe/appshell/nsWebShellWindow.h | 116 ++ xpfe/appshell/nsWindowMediator.cpp | 846 ++++++++ xpfe/appshell/nsWindowMediator.h | 78 + xpfe/appshell/nsXULWindow.cpp | 2334 +++++++++++++++++++++++ xpfe/appshell/nsXULWindow.h | 199 ++ xpfe/appshell/test/chrome.ini | 5 + xpfe/appshell/test/test_hiddenPrivateWindow.xul | 45 + xpfe/appshell/test/test_windowlessBrowser.xul | 75 + 27 files changed, 8928 insertions(+) create mode 100644 xpfe/appshell/moz.build create mode 100644 xpfe/appshell/nsAppShellCID.h create mode 100644 xpfe/appshell/nsAppShellFactory.cpp create mode 100644 xpfe/appshell/nsAppShellService.cpp create mode 100644 xpfe/appshell/nsAppShellService.h create mode 100644 xpfe/appshell/nsAppShellWindowEnumerator.cpp create mode 100644 xpfe/appshell/nsAppShellWindowEnumerator.h create mode 100644 xpfe/appshell/nsChromeTreeOwner.cpp create mode 100644 xpfe/appshell/nsChromeTreeOwner.h create mode 100644 xpfe/appshell/nsContentTreeOwner.cpp create mode 100644 xpfe/appshell/nsContentTreeOwner.h create mode 100644 xpfe/appshell/nsIAppShellService.idl create mode 100644 xpfe/appshell/nsIPopupWindowManager.idl create mode 100644 xpfe/appshell/nsIWindowMediator.idl create mode 100644 xpfe/appshell/nsIWindowMediatorListener.idl create mode 100644 xpfe/appshell/nsIWindowlessBrowser.idl create mode 100644 xpfe/appshell/nsIXULBrowserWindow.idl create mode 100644 xpfe/appshell/nsIXULWindow.idl create mode 100644 xpfe/appshell/nsWebShellWindow.cpp create mode 100644 xpfe/appshell/nsWebShellWindow.h create mode 100644 xpfe/appshell/nsWindowMediator.cpp create mode 100644 xpfe/appshell/nsWindowMediator.h create mode 100644 xpfe/appshell/nsXULWindow.cpp create mode 100644 xpfe/appshell/nsXULWindow.h create mode 100644 xpfe/appshell/test/chrome.ini create mode 100644 xpfe/appshell/test/test_hiddenPrivateWindow.xul create mode 100644 xpfe/appshell/test/test_windowlessBrowser.xul (limited to 'xpfe/appshell') diff --git a/xpfe/appshell/moz.build b/xpfe/appshell/moz.build new file mode 100644 index 000000000..5cfe41924 --- /dev/null +++ b/xpfe/appshell/moz.build @@ -0,0 +1,42 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini'] + +XPIDL_SOURCES += [ + 'nsIAppShellService.idl', + 'nsIPopupWindowManager.idl', + 'nsIWindowlessBrowser.idl', + 'nsIWindowMediator.idl', + 'nsIWindowMediatorListener.idl', + 'nsIXULBrowserWindow.idl', + 'nsIXULWindow.idl', +] + +XPIDL_MODULE = 'appshell' + +EXPORTS += [ + 'nsAppShellCID.h', +] + +UNIFIED_SOURCES += [ + 'nsAppShellFactory.cpp', + 'nsAppShellService.cpp', + 'nsAppShellWindowEnumerator.cpp', + 'nsChromeTreeOwner.cpp', + 'nsContentTreeOwner.cpp', + 'nsWebShellWindow.cpp', + 'nsWindowMediator.cpp', + 'nsXULWindow.cpp', +] + +LOCAL_INCLUDES += [ + '/dom/base', +] + +FINAL_LIBRARY = 'xul' + +include('/ipc/chromium/chromium-config.mozbuild') \ No newline at end of file diff --git a/xpfe/appshell/nsAppShellCID.h b/xpfe/appshell/nsAppShellCID.h new file mode 100644 index 000000000..2b0edd4ac --- /dev/null +++ b/xpfe/appshell/nsAppShellCID.h @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsAppShellCID_h__ +#define nsAppShellCID_h__ + +#define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1" + +#endif diff --git a/xpfe/appshell/nsAppShellFactory.cpp b/xpfe/appshell/nsAppShellFactory.cpp new file mode 100644 index 000000000..0b6d3c47a --- /dev/null +++ b/xpfe/appshell/nsAppShellFactory.cpp @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/ModuleUtils.h" +#include "nscore.h" +#include "nsIWindowMediator.h" + +#include "nsIAppShellService.h" +#include "nsAppShellService.h" +#include "nsWindowMediator.h" +#include "nsChromeTreeOwner.h" +#include "nsAppShellCID.h" + +NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShellService) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWindowMediator, Init) + +NS_DEFINE_NAMED_CID(NS_APPSHELLSERVICE_CID); +NS_DEFINE_NAMED_CID(NS_WINDOWMEDIATOR_CID); + +static const mozilla::Module::CIDEntry kAppShellCIDs[] = { + { &kNS_APPSHELLSERVICE_CID, false, nullptr, nsAppShellServiceConstructor }, + { &kNS_WINDOWMEDIATOR_CID, false, nullptr, nsWindowMediatorConstructor }, + { nullptr } +}; + +static const mozilla::Module::ContractIDEntry kAppShellContracts[] = { + { NS_APPSHELLSERVICE_CONTRACTID, &kNS_APPSHELLSERVICE_CID }, + { NS_WINDOWMEDIATOR_CONTRACTID, &kNS_WINDOWMEDIATOR_CID }, + { nullptr } +}; + +static nsresult +nsAppShellModuleConstructor() +{ + return nsChromeTreeOwner::InitGlobals(); +} + +static void +nsAppShellModuleDestructor() +{ + nsChromeTreeOwner::FreeGlobals(); +} + +static const mozilla::Module kAppShellModule = { + mozilla::Module::kVersion, + kAppShellCIDs, + kAppShellContracts, + nullptr, + nullptr, + nsAppShellModuleConstructor, + nsAppShellModuleDestructor +}; + +NSMODULE_DEFN(appshell) = &kAppShellModule; diff --git a/xpfe/appshell/nsAppShellService.cpp b/xpfe/appshell/nsAppShellService.cpp new file mode 100644 index 000000000..7e1ddf16c --- /dev/null +++ b/xpfe/appshell/nsAppShellService.cpp @@ -0,0 +1,1001 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +#include "nsIAppShellService.h" +#include "nsIComponentManager.h" +#include "nsIURL.h" +#include "nsNetUtil.h" +#include "nsIServiceManager.h" +#include "nsIObserverService.h" +#include "nsIObserver.h" +#include "nsIXPConnect.h" +#include "nsIXULRuntime.h" + +#include "nsIWindowMediator.h" +#include "nsIWindowWatcher.h" +#include "nsPIWindowWatcher.h" +#include "nsIDOMWindow.h" +#include "nsPIDOMWindow.h" +#include "nsWebShellWindow.h" + +#include "prprf.h" + +#include "nsWidgetInitData.h" +#include "nsWidgetsCID.h" +#include "nsIWidget.h" +#include "nsIRequestObserver.h" +#include "nsIEmbeddingSiteWindow.h" + +#include "nsAppShellService.h" +#include "nsContentUtils.h" +#include "nsThreadUtils.h" +#include "nsISupportsPrimitives.h" +#include "nsIChromeRegistry.h" +#include "nsILoadContext.h" +#include "nsIWebNavigation.h" +#include "nsIWindowlessBrowser.h" + +#include "mozilla/Attributes.h" +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "mozilla/StartupTimeline.h" + +#include "nsEmbedCID.h" +#include "nsIWebBrowser.h" +#include "nsIDocShell.h" + +#ifdef MOZ_INSTRUMENT_EVENT_LOOP +#include "EventTracer.h" +#endif + +using namespace mozilla; + +// Default URL for the hidden window, can be overridden by a pref on Mac +#define DEFAULT_HIDDENWINDOW_URL "resource://gre-resources/hiddenWindow.html" + +class nsIAppShell; + +nsAppShellService::nsAppShellService() : + mXPCOMWillShutDown(false), + mXPCOMShuttingDown(false), + mModalWindowCount(0), + mApplicationProvidedHiddenWindow(false), + mScreenId(0) +{ + nsCOMPtr obs = services::GetObserverService(); + + if (obs) { + obs->AddObserver(this, "xpcom-will-shutdown", false); + obs->AddObserver(this, "xpcom-shutdown", false); + } +} + +nsAppShellService::~nsAppShellService() +{ +} + + +/* + * Implement the nsISupports methods... + */ +NS_IMPL_ISUPPORTS(nsAppShellService, + nsIAppShellService, + nsIObserver) + +NS_IMETHODIMP +nsAppShellService::CreateHiddenWindow() +{ + return CreateHiddenWindowHelper(false); +} + +NS_IMETHODIMP +nsAppShellService::SetScreenId(uint32_t aScreenId) +{ + mScreenId = aScreenId; + return NS_OK; +} + +void +nsAppShellService::EnsurePrivateHiddenWindow() +{ + if (!mHiddenPrivateWindow) { + CreateHiddenWindowHelper(true); + } +} + +nsresult +nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate) +{ + nsresult rv; + int32_t initialHeight = 100, initialWidth = 100; + +#ifdef XP_MACOSX + uint32_t chromeMask = 0; + nsAdoptingCString prefVal = + Preferences::GetCString("browser.hiddenWindowChromeURL"); + const char* hiddenWindowURL = prefVal.get() ? prefVal.get() : DEFAULT_HIDDENWINDOW_URL; + if (aIsPrivate) { + hiddenWindowURL = DEFAULT_HIDDENWINDOW_URL; + } else { + mApplicationProvidedHiddenWindow = prefVal.get() ? true : false; + } +#else + static const char hiddenWindowURL[] = DEFAULT_HIDDENWINDOW_URL; + uint32_t chromeMask = nsIWebBrowserChrome::CHROME_ALL; +#endif + + nsCOMPtr url; + rv = NS_NewURI(getter_AddRefs(url), hiddenWindowURL); + NS_ENSURE_SUCCESS(rv, rv); + + RefPtr newWindow; + if (!aIsPrivate) { + rv = JustCreateTopWindow(nullptr, url, + chromeMask, initialWidth, initialHeight, + true, nullptr, nullptr, getter_AddRefs(newWindow)); + NS_ENSURE_SUCCESS(rv, rv); + + mHiddenWindow.swap(newWindow); + } else { + // Create the hidden private window + chromeMask |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW; + + rv = JustCreateTopWindow(nullptr, url, + chromeMask, initialWidth, initialHeight, + true, nullptr, nullptr, getter_AddRefs(newWindow)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr docShell; + newWindow->GetDocShell(getter_AddRefs(docShell)); + if (docShell) { + docShell->SetAffectPrivateSessionLifetime(false); + } + + mHiddenPrivateWindow.swap(newWindow); + } + + // RegisterTopLevelWindow(newWindow); -- Mac only + + return NS_OK; +} + +NS_IMETHODIMP +nsAppShellService::DestroyHiddenWindow() +{ + if (mHiddenWindow) { + mHiddenWindow->Destroy(); + + mHiddenWindow = nullptr; + } + + if (mHiddenPrivateWindow) { + mHiddenPrivateWindow->Destroy(); + + mHiddenPrivateWindow = nullptr; + } + + return NS_OK; +} + +/* + * Create a new top level window and display the given URL within it... + */ +NS_IMETHODIMP +nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent, + nsIURI *aUrl, + uint32_t aChromeMask, + int32_t aInitialWidth, + int32_t aInitialHeight, + nsITabParent *aOpeningTab, + mozIDOMWindowProxy *aOpenerWindow, + nsIXULWindow **aResult) + +{ + nsresult rv; + + StartupTimeline::RecordOnce(StartupTimeline::CREATE_TOP_LEVEL_WINDOW); + + RefPtr newWindow; + rv = JustCreateTopWindow(aParent, aUrl, + aChromeMask, aInitialWidth, aInitialHeight, + false, aOpeningTab, aOpenerWindow, + getter_AddRefs(newWindow)); + newWindow.forget(aResult); + + if (NS_SUCCEEDED(rv)) { + // the addref resulting from this is the owning addref for this window + RegisterTopLevelWindow(*aResult); + nsCOMPtr parent; + if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT) + parent = aParent; + (*aResult)->SetZLevel(CalculateWindowZLevel(parent, aChromeMask)); + } + + return rv; +} + +/* + * This class provides a stub implementation of nsIWebBrowserChrome2, as needed + * by nsAppShellService::CreateWindowlessBrowser + */ +class WebBrowserChrome2Stub : public nsIWebBrowserChrome2, + public nsIEmbeddingSiteWindow, + public nsIInterfaceRequestor, + public nsSupportsWeakReference { +protected: + virtual ~WebBrowserChrome2Stub() {} +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIWEBBROWSERCHROME + NS_DECL_NSIWEBBROWSERCHROME2 + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSIEMBEDDINGSITEWINDOW +}; + +NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(WebBrowserChrome2Stub) +NS_IMPL_RELEASE(WebBrowserChrome2Stub) + +NS_IMETHODIMP +WebBrowserChrome2Stub::SetStatus(uint32_t aStatusType, const char16_t* aStatus) +{ + return NS_OK; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::GetWebBrowser(nsIWebBrowser** aWebBrowser) +{ + NS_NOTREACHED("WebBrowserChrome2Stub::GetWebBrowser is not supported"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::SetWebBrowser(nsIWebBrowser* aWebBrowser) +{ + NS_NOTREACHED("WebBrowserChrome2Stub::SetWebBrowser is not supported"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::GetChromeFlags(uint32_t* aChromeFlags) +{ + *aChromeFlags = 0; + return NS_OK; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::SetChromeFlags(uint32_t aChromeFlags) +{ + NS_NOTREACHED("WebBrowserChrome2Stub::SetChromeFlags is not supported"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::DestroyBrowserWindow() +{ + NS_NOTREACHED("WebBrowserChrome2Stub::DestroyBrowserWindow is not supported"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::SizeBrowserTo(int32_t aCX, int32_t aCY) +{ + NS_NOTREACHED("WebBrowserChrome2Stub::SizeBrowserTo is not supported"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::ShowAsModal() +{ + NS_NOTREACHED("WebBrowserChrome2Stub::ShowAsModal is not supported"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::IsWindowModal(bool* aResult) +{ + *aResult = false; + return NS_OK; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::ExitModalEventLoop(nsresult aStatus) +{ + NS_NOTREACHED("WebBrowserChrome2Stub::ExitModalEventLoop is not supported"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::SetStatusWithContext(uint32_t aStatusType, + const nsAString& aStatusText, + nsISupports* aStatusContext) +{ + return NS_OK; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::GetInterface(const nsIID& aIID, void** aSink) +{ + return QueryInterface(aIID, aSink); +} + +// nsIEmbeddingSiteWindow impl +NS_IMETHODIMP +WebBrowserChrome2Stub::GetDimensions(uint32_t flags, int32_t* x, int32_t* y, int32_t* cx, int32_t* cy) +{ + if (x) { + *x = 0; + } + + if (y) { + *y = 0; + } + + if (cx) { + *cx = 0; + } + + if (cy) { + *cy = 0; + } + + return NS_OK; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::SetDimensions(uint32_t flags, int32_t x, int32_t y, int32_t cx, int32_t cy) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::SetFocus() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::GetVisibility(bool* aVisibility) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP +WebBrowserChrome2Stub::SetVisibility(bool aVisibility) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::GetTitle(char16_t** aTitle) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP +WebBrowserChrome2Stub::SetTitle(const char16_t* aTitle) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::GetSiteWindow(void** aSiteWindow) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +WebBrowserChrome2Stub::Blur() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +class BrowserDestroyer final : public Runnable +{ +public: + BrowserDestroyer(nsIWebBrowser *aBrowser, nsISupports *aContainer) : + mBrowser(aBrowser), + mContainer(aContainer) + { + } + + NS_IMETHOD + Run() override + { + // Explicitly destroy the browser, in case this isn't the last reference. + nsCOMPtr window = do_QueryInterface(mBrowser); + return window->Destroy(); + } + +protected: + virtual ~BrowserDestroyer() {} + +private: + nsCOMPtr mBrowser; + nsCOMPtr mContainer; +}; + +// This is the "stub" we return from CreateWindowlessBrowser - it exists +// to manage the lifetimes of the nsIWebBrowser and container window. +// In particular, it keeps a strong reference to both, to prevent them from +// being collected while this object remains alive, and ensures that they +// aren't destroyed when it's not safe to run scripts. +class WindowlessBrowser final : public nsIWindowlessBrowser, + public nsIInterfaceRequestor +{ +public: + WindowlessBrowser(nsIWebBrowser *aBrowser, nsISupports *aContainer) : + mBrowser(aBrowser), + mContainer(aContainer), + mClosed(false) + { + mWebNavigation = do_QueryInterface(aBrowser); + mInterfaceRequestor = do_QueryInterface(aBrowser); + } + NS_DECL_ISUPPORTS + NS_FORWARD_SAFE_NSIWEBNAVIGATION(mWebNavigation) + NS_FORWARD_SAFE_NSIINTERFACEREQUESTOR(mInterfaceRequestor) + + NS_IMETHOD + Close() override + { + NS_ENSURE_TRUE(!mClosed, NS_ERROR_UNEXPECTED); + NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), + "WindowlessBrowser::Close called when not safe to run scripts"); + + mClosed = true; + + mWebNavigation = nullptr; + mInterfaceRequestor = nullptr; + + nsCOMPtr window = do_QueryInterface(mBrowser); + return window->Destroy(); + } + +protected: + virtual ~WindowlessBrowser() + { + if (mClosed) { + return; + } + + NS_WARNING("Windowless browser was not closed prior to destruction"); + + // The docshell destructor needs to dispatch events, and can only run + // when it's safe to run scripts. If this was triggered by GC, it may + // not always be safe to run scripts, in which cases we need to delay + // destruction until it is. + nsCOMPtr runnable = new BrowserDestroyer(mBrowser, mContainer); + nsContentUtils::AddScriptRunner(runnable); + } + +private: + nsCOMPtr mBrowser; + nsCOMPtr mWebNavigation; + nsCOMPtr mInterfaceRequestor; + // we don't use the container but just hold a reference to it. + nsCOMPtr mContainer; + + bool mClosed; +}; + +NS_IMPL_ISUPPORTS(WindowlessBrowser, nsIWindowlessBrowser, nsIWebNavigation, nsIInterfaceRequestor) + + +NS_IMETHODIMP +nsAppShellService::CreateWindowlessBrowser(bool aIsChrome, nsIWindowlessBrowser **aResult) +{ + /* First, we create an instance of nsWebBrowser. Instances of this class have + * an associated doc shell, which is what we're interested in. + */ + nsCOMPtr browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID); + if (!browser) { + NS_ERROR("Couldn't create instance of nsWebBrowser!"); + return NS_ERROR_FAILURE; + } + + /* Next, we set the container window for our instance of nsWebBrowser. Since + * we don't actually have a window, we instead set the container window to be + * an instance of WebBrowserChrome2Stub, which provides a stub implementation + * of nsIWebBrowserChrome2. + */ + RefPtr stub = new WebBrowserChrome2Stub(); + browser->SetContainerWindow(stub); + + nsCOMPtr navigation = do_QueryInterface(browser); + + nsCOMPtr item = do_QueryInterface(navigation); + item->SetItemType(aIsChrome ? nsIDocShellTreeItem::typeChromeWrapper + : nsIDocShellTreeItem::typeContentWrapper); + + /* A windowless web browser doesn't have an associated OS level window. To + * accomplish this, we initialize the window associated with our instance of + * nsWebBrowser with an instance of PuppetWidget, which provides a stub + * implementation of nsIWidget. + */ + nsCOMPtr widget = nsIWidget::CreatePuppetWidget(nullptr); + if (!widget) { + NS_ERROR("Couldn't create instance of PuppetWidget"); + return NS_ERROR_FAILURE; + } + nsresult rv = + widget->Create(nullptr, 0, LayoutDeviceIntRect(0, 0, 0, 0), nullptr); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr window = do_QueryInterface(navigation); + window->InitWindow(0, widget, 0, 0, 0, 0); + window->Create(); + + nsISupports *isstub = NS_ISUPPORTS_CAST(nsIWebBrowserChrome2*, stub); + RefPtr result = new WindowlessBrowser(browser, isstub); + nsCOMPtr docshell = do_GetInterface(result); + docshell->SetInvisible(true); + + result.forget(aResult); + return NS_OK; +} + +uint32_t +nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent, + uint32_t aChromeMask) +{ + uint32_t zLevel; + + zLevel = nsIXULWindow::normalZ; + if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RAISED) + zLevel = nsIXULWindow::raisedZ; + else if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_LOWERED) + zLevel = nsIXULWindow::loweredZ; + +#ifdef XP_MACOSX + /* Platforms on which modal windows are always application-modal, not + window-modal (that's just the Mac, right?) want modal windows to + be stacked on top of everyone else. + + On Mac OS X, bind modality to parent window instead of app (ala Mac OS 9) + */ + uint32_t modalDepMask = nsIWebBrowserChrome::CHROME_MODAL | + nsIWebBrowserChrome::CHROME_DEPENDENT; + if (aParent && (aChromeMask & modalDepMask)) { + aParent->GetZLevel(&zLevel); + } +#else + /* Platforms with native support for dependent windows (that's everyone + but pre-Mac OS X, right?) know how to stack dependent windows. On these + platforms, give the dependent window the same level as its parent, + so we won't try to override the normal platform behaviour. */ + if ((aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT) && aParent) + aParent->GetZLevel(&zLevel); +#endif + + return zLevel; +} + +#ifdef XP_WIN +/* + * Checks to see if any existing window is currently in fullscreen mode. + */ +static bool +CheckForFullscreenWindow() +{ + nsCOMPtr wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); + if (!wm) + return false; + + nsCOMPtr windowList; + wm->GetXULWindowEnumerator(nullptr, getter_AddRefs(windowList)); + if (!windowList) + return false; + + for (;;) { + bool more = false; + windowList->HasMoreElements(&more); + if (!more) + return false; + + nsCOMPtr supportsWindow; + windowList->GetNext(getter_AddRefs(supportsWindow)); + nsCOMPtr baseWin(do_QueryInterface(supportsWindow)); + if (baseWin) { + nsCOMPtr widget; + baseWin->GetMainWidget(getter_AddRefs(widget)); + if (widget && widget->SizeMode() == nsSizeMode_Fullscreen) { + return true; + } + } + } + return false; +} +#endif + +/* + * Just do the window-making part of CreateTopLevelWindow + */ +nsresult +nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent, + nsIURI *aUrl, + uint32_t aChromeMask, + int32_t aInitialWidth, + int32_t aInitialHeight, + bool aIsHiddenWindow, + nsITabParent *aOpeningTab, + mozIDOMWindowProxy *aOpenerWindow, + nsWebShellWindow **aResult) +{ + *aResult = nullptr; + NS_ENSURE_STATE(!mXPCOMWillShutDown); + + nsCOMPtr parent; + if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT) + parent = aParent; + + RefPtr window = new nsWebShellWindow(aChromeMask); + +#ifdef XP_WIN + // If the parent is currently fullscreen, tell the child to ignore persisted + // full screen states. This way new browser windows open on top of fullscreen + // windows normally. + if (window && CheckForFullscreenWindow()) + window->IgnoreXULSizeMode(true); +#endif + + nsWidgetInitData widgetInitData; + + if (aIsHiddenWindow) + widgetInitData.mWindowType = eWindowType_invisible; + else + widgetInitData.mWindowType = aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG ? + eWindowType_dialog : eWindowType_toplevel; + + if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_POPUP) + widgetInitData.mWindowType = eWindowType_popup; + + if (aChromeMask & nsIWebBrowserChrome::CHROME_MAC_SUPPRESS_ANIMATION) + widgetInitData.mIsAnimationSuppressed = true; + +#ifdef XP_MACOSX + // Mac OS X sheet support + // Adding CHROME_OPENAS_CHROME to sheetMask makes modal windows opened from + // nsGlobalWindow::ShowModalDialog() be dialogs (not sheets), while modal + // windows opened from nsPromptService::DoDialog() still are sheets. This + // fixes bmo bug 395465 (see nsCocoaWindow::StandardCreate() and + // nsCocoaWindow::SetModal()). + uint32_t sheetMask = nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | + nsIWebBrowserChrome::CHROME_MODAL | + nsIWebBrowserChrome::CHROME_OPENAS_CHROME; + if (parent && + (parent != mHiddenWindow && parent != mHiddenPrivateWindow) && + ((aChromeMask & sheetMask) == sheetMask)) { + widgetInitData.mWindowType = eWindowType_sheet; + } +#endif + +#if defined(XP_WIN) + if (widgetInitData.mWindowType == eWindowType_toplevel || + widgetInitData.mWindowType == eWindowType_dialog) + widgetInitData.clipChildren = true; +#endif + + // note default chrome overrides other OS chrome settings, but + // not internal chrome + if (aChromeMask & nsIWebBrowserChrome::CHROME_DEFAULT) + widgetInitData.mBorderStyle = eBorderStyle_default; + else if ((aChromeMask & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL) + widgetInitData.mBorderStyle = eBorderStyle_all; + else { + widgetInitData.mBorderStyle = eBorderStyle_none; // assumes none == 0x00 + if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_BORDERS) + widgetInitData.mBorderStyle = static_cast(widgetInitData.mBorderStyle | eBorderStyle_border); + if (aChromeMask & nsIWebBrowserChrome::CHROME_TITLEBAR) + widgetInitData.mBorderStyle = static_cast(widgetInitData.mBorderStyle | eBorderStyle_title); + if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_CLOSE) + widgetInitData.mBorderStyle = static_cast(widgetInitData.mBorderStyle | eBorderStyle_close); + if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) { + widgetInitData.mBorderStyle = static_cast(widgetInitData.mBorderStyle | eBorderStyle_resizeh); + // only resizable windows get the maximize button (but not dialogs) + if (!(aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG)) + widgetInitData.mBorderStyle = static_cast(widgetInitData.mBorderStyle | eBorderStyle_maximize); + } + // all windows (except dialogs) get minimize buttons and the system menu + if (!(aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG)) + widgetInitData.mBorderStyle = static_cast(widgetInitData.mBorderStyle | eBorderStyle_minimize | eBorderStyle_menu); + // but anyone can explicitly ask for a minimize button + if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_MIN) { + widgetInitData.mBorderStyle = static_cast(widgetInitData.mBorderStyle | eBorderStyle_minimize); + } + } + + if (aInitialWidth == nsIAppShellService::SIZE_TO_CONTENT || + aInitialHeight == nsIAppShellService::SIZE_TO_CONTENT) { + aInitialWidth = 1; + aInitialHeight = 1; + window->SetIntrinsicallySized(true); + } + + bool center = aChromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN; + + nsCOMPtr reg = + mozilla::services::GetXULChromeRegistryService(); + if (reg) { + nsAutoCString package; + package.AssignLiteral("global"); + bool isRTL = false; + reg->IsLocaleRTL(package, &isRTL); + widgetInitData.mRTL = isRTL; + } + +#ifdef MOZ_WIDGET_GONK + // B2G multi-screen support. Screen ID is for differentiating screens of + // windows, and due to the hardware limitation, it is platform-specific for + // now, which align with the value of display type defined in HWC. + widgetInitData.mScreenId = mScreenId; +#endif + + nsresult rv = window->Initialize(parent, center ? aParent : nullptr, + aUrl, aInitialWidth, aInitialHeight, + aIsHiddenWindow, aOpeningTab, + aOpenerWindow, widgetInitData); + + NS_ENSURE_SUCCESS(rv, rv); + + // Enforce the Private Browsing autoStart pref first. + bool isPrivateBrowsingWindow = + Preferences::GetBool("browser.privatebrowsing.autostart"); + bool isUsingRemoteTabs = mozilla::BrowserTabsRemoteAutostart(); + + if (aChromeMask & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW) { + // Caller requested a private window + isPrivateBrowsingWindow = true; + } + if (aChromeMask & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW) { + isUsingRemoteTabs = true; + } + + nsCOMPtr domWin = do_GetInterface(aParent); + nsCOMPtr webNav = do_GetInterface(domWin); + nsCOMPtr parentContext = do_QueryInterface(webNav); + + if (!isPrivateBrowsingWindow && parentContext) { + // Ensure that we propagate any existing private browsing status + // from the parent, even if it will not actually be used + // as a parent value. + isPrivateBrowsingWindow = parentContext->UsePrivateBrowsing(); + } + + if (parentContext) { + isUsingRemoteTabs = parentContext->UseRemoteTabs(); + } + + nsCOMPtr newDomWin = + do_GetInterface(NS_ISUPPORTS_CAST(nsIBaseWindow*, window)); + nsCOMPtr newWebNav = do_GetInterface(newDomWin); + nsCOMPtr thisContext = do_GetInterface(newWebNav); + if (thisContext) { + thisContext->SetPrivateBrowsing(isPrivateBrowsingWindow); + thisContext->SetRemoteTabs(isUsingRemoteTabs); + } + + window.forget(aResult); + if (parent) + parent->AddChildWindow(*aResult); + + if (center) + rv = (*aResult)->Center(parent, parent ? false : true, false); + + return rv; +} + +NS_IMETHODIMP +nsAppShellService::GetHiddenWindow(nsIXULWindow **aWindow) +{ + NS_ENSURE_ARG_POINTER(aWindow); + + *aWindow = mHiddenWindow; + NS_IF_ADDREF(*aWindow); + return *aWindow ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsAppShellService::GetHiddenDOMWindow(mozIDOMWindowProxy **aWindow) +{ + nsresult rv; + nsCOMPtr docShell; + NS_ENSURE_TRUE(mHiddenWindow, NS_ERROR_FAILURE); + + rv = mHiddenWindow->GetDocShell(getter_AddRefs(docShell)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); + + nsCOMPtr hiddenDOMWindow(docShell->GetWindow()); + hiddenDOMWindow.forget(aWindow); + return *aWindow ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsAppShellService::GetHiddenPrivateWindow(nsIXULWindow **aWindow) +{ + NS_ENSURE_ARG_POINTER(aWindow); + + EnsurePrivateHiddenWindow(); + + *aWindow = mHiddenPrivateWindow; + NS_IF_ADDREF(*aWindow); + return *aWindow ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsAppShellService::GetHiddenPrivateDOMWindow(mozIDOMWindowProxy **aWindow) +{ + EnsurePrivateHiddenWindow(); + + nsresult rv; + nsCOMPtr docShell; + NS_ENSURE_TRUE(mHiddenPrivateWindow, NS_ERROR_FAILURE); + + rv = mHiddenPrivateWindow->GetDocShell(getter_AddRefs(docShell)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); + + nsCOMPtr hiddenPrivateDOMWindow(docShell->GetWindow()); + hiddenPrivateDOMWindow.forget(aWindow); + return *aWindow ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsAppShellService::GetHasHiddenPrivateWindow(bool* aHasPrivateWindow) +{ + NS_ENSURE_ARG_POINTER(aHasPrivateWindow); + + *aHasPrivateWindow = !!mHiddenPrivateWindow; + return NS_OK; +} + +NS_IMETHODIMP +nsAppShellService::GetApplicationProvidedHiddenWindow(bool* aAPHW) +{ + *aAPHW = mApplicationProvidedHiddenWindow; + return NS_OK; +} + +/* + * Register a new top level window (created elsewhere) + */ +NS_IMETHODIMP +nsAppShellService::RegisterTopLevelWindow(nsIXULWindow* aWindow) +{ + NS_ENSURE_ARG_POINTER(aWindow); + + nsCOMPtr docShell; + aWindow->GetDocShell(getter_AddRefs(docShell)); + NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); + + nsCOMPtr domWindow(docShell->GetWindow()); + NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE); + domWindow->SetInitialPrincipalToSubject(); + + // tell the window mediator about the new window + nsCOMPtr mediator + ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID) ); + NS_ASSERTION(mediator, "Couldn't get window mediator."); + + if (mediator) + mediator->RegisterWindow(aWindow); + + // tell the window watcher about the new window + nsCOMPtr wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID) ); + NS_ASSERTION(wwatcher, "No windowwatcher?"); + if (wwatcher && domWindow) { + wwatcher->AddWindow(domWindow, 0); + } + + // an ongoing attempt to quit is stopped by a newly opened window + nsCOMPtr obssvc = services::GetObserverService(); + NS_ASSERTION(obssvc, "Couldn't get observer service."); + + if (obssvc) { + obssvc->NotifyObservers(aWindow, "xul-window-registered", nullptr); + nsXULWindow* xulWindow = static_cast(aWindow); + xulWindow->WasRegistered(); + } + + return NS_OK; +} + + +NS_IMETHODIMP +nsAppShellService::UnregisterTopLevelWindow(nsIXULWindow* aWindow) +{ + if (mXPCOMShuttingDown) { + /* return an error code in order to: + - avoid doing anything with other member variables while we are in + the destructor + - notify the caller not to release the AppShellService after + unregistering the window + (we don't want to be deleted twice consecutively to + mHiddenWindow->Destroy() in our destructor) + */ + return NS_ERROR_FAILURE; + } + + NS_ENSURE_ARG_POINTER(aWindow); + + if (aWindow == mHiddenWindow) { + // CreateHiddenWindow() does not register the window, so we're done. + return NS_OK; + } + if (aWindow == mHiddenPrivateWindow) { + // CreateHiddenWindow() does not register the window, so we're done. + return NS_OK; + } + + // tell the window mediator + nsCOMPtr mediator + ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID) ); + NS_ASSERTION(mediator, "Couldn't get window mediator. Doing xpcom shutdown?"); + + if (mediator) + mediator->UnregisterWindow(aWindow); + + // tell the window watcher + nsCOMPtr wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID) ); + NS_ASSERTION(wwatcher, "Couldn't get windowwatcher, doing xpcom shutdown?"); + if (wwatcher) { + nsCOMPtr docShell; + aWindow->GetDocShell(getter_AddRefs(docShell)); + if (docShell) { + nsCOMPtr domWindow(docShell->GetWindow()); + if (domWindow) + wwatcher->RemoveWindow(domWindow); + } + } + + return NS_OK; +} + + +NS_IMETHODIMP +nsAppShellService::Observe(nsISupports* aSubject, const char *aTopic, + const char16_t *aData) +{ + if (!strcmp(aTopic, "xpcom-will-shutdown")) { + mXPCOMWillShutDown = true; + } else if (!strcmp(aTopic, "xpcom-shutdown")) { + mXPCOMShuttingDown = true; + if (mHiddenWindow) { + mHiddenWindow->Destroy(); + } + if (mHiddenPrivateWindow) { + mHiddenPrivateWindow->Destroy(); + } + } else { + NS_ERROR("Unexpected observer topic!"); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsAppShellService::StartEventLoopLagTracking(bool* aResult) +{ +#ifdef MOZ_INSTRUMENT_EVENT_LOOP + *aResult = mozilla::InitEventTracing(true); +#endif + return NS_OK; +} + +NS_IMETHODIMP +nsAppShellService::StopEventLoopLagTracking() +{ +#ifdef MOZ_INSTRUMENT_EVENT_LOOP + mozilla::ShutdownEventTracing(); +#endif + return NS_OK; +} diff --git a/xpfe/appshell/nsAppShellService.h b/xpfe/appshell/nsAppShellService.h new file mode 100644 index 000000000..feb7b9947 --- /dev/null +++ b/xpfe/appshell/nsAppShellService.h @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __nsAppShellService_h +#define __nsAppShellService_h + +#include "nsIAppShellService.h" +#include "nsIObserver.h" + +//Interfaces Needed +#include "nsWebShellWindow.h" +#include "nsStringFwd.h" +#include "nsAutoPtr.h" +#include "nsITabParent.h" +#include "mozilla/Attributes.h" + +// {0099907D-123C-4853-A46A-43098B5FB68C} +#define NS_APPSHELLSERVICE_CID \ +{ 0x99907d, 0x123c, 0x4853, { 0xa4, 0x6a, 0x43, 0x9, 0x8b, 0x5f, 0xb6, 0x8c } } + +class nsAppShellService final : public nsIAppShellService, + public nsIObserver +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIAPPSHELLSERVICE + NS_DECL_NSIOBSERVER + + nsAppShellService(); + +protected: + ~nsAppShellService(); + + nsresult CreateHiddenWindowHelper(bool aIsPrivate); + void EnsurePrivateHiddenWindow(); + + nsresult JustCreateTopWindow(nsIXULWindow *aParent, + nsIURI *aUrl, + uint32_t aChromeMask, + int32_t aInitialWidth, int32_t aInitialHeight, + bool aIsHiddenWindow, + nsITabParent *aOpeningTab, + mozIDOMWindowProxy *aOpenerWindow, + nsWebShellWindow **aResult); + uint32_t CalculateWindowZLevel(nsIXULWindow *aParent, uint32_t aChromeMask); + + RefPtr mHiddenWindow; + RefPtr mHiddenPrivateWindow; + bool mXPCOMWillShutDown; + bool mXPCOMShuttingDown; + uint16_t mModalWindowCount; + bool mApplicationProvidedHiddenWindow; + uint32_t mScreenId; +}; + +#endif diff --git a/xpfe/appshell/nsAppShellWindowEnumerator.cpp b/xpfe/appshell/nsAppShellWindowEnumerator.cpp new file mode 100644 index 000000000..dc5fc120a --- /dev/null +++ b/xpfe/appshell/nsAppShellWindowEnumerator.cpp @@ -0,0 +1,495 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsAppShellWindowEnumerator.h" + +#include "nsIContentViewer.h" +#include "nsIDocShell.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsIDOMElement.h" +#include "nsIDOMWindow.h" +#include "nsIFactory.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIXULWindow.h" + +#include "nsWindowMediator.h" + +// +// static helper functions +// + +static nsCOMPtr GetDOMNodeFromDocShell(nsIDocShell *aShell); +static void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute, + nsAString &outValue); +static void GetWindowType(nsIXULWindow* inWindow, nsString &outType); + +nsCOMPtr GetDOMNodeFromDocShell(nsIDocShell *aShell) +{ + nsCOMPtr node; + + nsCOMPtr cv; + aShell->GetContentViewer(getter_AddRefs(cv)); + if (cv) { + nsCOMPtr domdoc(do_QueryInterface(cv->GetDocument())); + if (domdoc) { + nsCOMPtr element; + domdoc->GetDocumentElement(getter_AddRefs(element)); + if (element) + node = element; + } + } + + return node; +} + +// generic "retrieve the value of a XUL attribute" function +void GetAttribute(nsIXULWindow *inWindow, const nsAString &inAttribute, + nsAString &outValue) +{ + nsCOMPtr shell; + if (inWindow && NS_SUCCEEDED(inWindow->GetDocShell(getter_AddRefs(shell)))) { + nsCOMPtr node(GetDOMNodeFromDocShell(shell)); + if (node) { + nsCOMPtr webshellElement(do_QueryInterface(node)); + if (webshellElement) + webshellElement->GetAttribute(inAttribute, outValue); + } + } +} + +// retrieve the window type, stored as the value of a particular +// attribute in its XUL window tag +void GetWindowType(nsIXULWindow* aWindow, nsString &outType) +{ + GetAttribute(aWindow, NS_LITERAL_STRING("windowtype"), outType); +} + +// +// nsWindowInfo +// + +nsWindowInfo::nsWindowInfo(nsIXULWindow* inWindow, int32_t inTimeStamp) : + mWindow(inWindow),mTimeStamp(inTimeStamp),mZLevel(nsIXULWindow::normalZ) +{ + ReferenceSelf(true, true); +} + +nsWindowInfo::~nsWindowInfo() +{ +} + +// return true if the window described by this WindowInfo has a type +// equal to the given type +bool nsWindowInfo::TypeEquals(const nsAString &aType) +{ + nsAutoString rtnString; + GetWindowType(mWindow, rtnString); + return rtnString == aType; +} + +// insert the struct into their two linked lists, in position after the +// given (independent) method arguments +void nsWindowInfo::InsertAfter(nsWindowInfo *inOlder , nsWindowInfo *inHigher) +{ + if (inOlder) { + mOlder = inOlder; + mYounger = inOlder->mYounger; + mOlder->mYounger = this; + if (mOlder->mOlder == mOlder) + mOlder->mOlder = this; + mYounger->mOlder = this; + if (mYounger->mYounger == mYounger) + mYounger->mYounger = this; + } + if (inHigher) { + mHigher = inHigher; + mLower = inHigher->mLower; + mHigher->mLower = this; + if (mHigher->mHigher == mHigher) + mHigher->mHigher = this; + mLower->mHigher = this; + if (mLower->mLower == mLower) + mLower->mLower = this; + } +} + +// remove the struct from its linked lists +void nsWindowInfo::Unlink(bool inAge, bool inZ) +{ + if (inAge) { + mOlder->mYounger = mYounger; + mYounger->mOlder = mOlder; + } + if (inZ) { + mLower->mHigher = mHigher; + mHigher->mLower = mLower; + } + ReferenceSelf(inAge, inZ); +} + +// initialize the struct to be a valid linked list of one element +void nsWindowInfo::ReferenceSelf(bool inAge, bool inZ) +{ + if (inAge) { + mYounger = this; + mOlder = this; + } + if (inZ) { + mLower = this; + mHigher = this; + } +} + +// +// nsAppShellWindowEnumerator +// + +NS_IMPL_ISUPPORTS(nsAppShellWindowEnumerator, nsISimpleEnumerator) + +nsAppShellWindowEnumerator::nsAppShellWindowEnumerator( + const char16_t* aTypeString, + nsWindowMediator& aMediator) : + mWindowMediator(&aMediator), mType(aTypeString), mCurrentPosition(nullptr) +{ + mWindowMediator->AddEnumerator(this); + NS_ADDREF(mWindowMediator); +} + +nsAppShellWindowEnumerator::~nsAppShellWindowEnumerator() +{ + mWindowMediator->RemoveEnumerator(this); + NS_RELEASE(mWindowMediator); +} + +// after mCurrentPosition has been initialized to point to the beginning +// of the appropriate list, adjust it if necessary +void nsAppShellWindowEnumerator::AdjustInitialPosition() +{ + if (!mType.IsEmpty() && mCurrentPosition && !mCurrentPosition->TypeEquals(mType)) + mCurrentPosition = FindNext(); +} + +NS_IMETHODIMP nsAppShellWindowEnumerator::HasMoreElements(bool *retval) +{ + if (!retval) + return NS_ERROR_INVALID_ARG; + + *retval = mCurrentPosition ? true : false; + return NS_OK; +} + +// if a window is being removed adjust the iterator's current position +void nsAppShellWindowEnumerator::WindowRemoved(nsWindowInfo *inInfo) +{ + if (mCurrentPosition == inInfo) + mCurrentPosition = FindNext(); +} + +// +// nsASDOMWindowEnumerator +// + +nsASDOMWindowEnumerator::nsASDOMWindowEnumerator( + const char16_t* aTypeString, + nsWindowMediator& aMediator) : + nsAppShellWindowEnumerator(aTypeString, aMediator) +{ +} + +nsASDOMWindowEnumerator::~nsASDOMWindowEnumerator() +{ +} + +NS_IMETHODIMP nsASDOMWindowEnumerator::GetNext(nsISupports **retval) +{ + if (!retval) + return NS_ERROR_INVALID_ARG; + + *retval = nullptr; + while (mCurrentPosition) { + nsCOMPtr domWindow; + nsWindowMediator::GetDOMWindow(mCurrentPosition->mWindow, domWindow); + mCurrentPosition = FindNext(); + if (domWindow) + return CallQueryInterface(domWindow, retval); + } + return NS_OK; +} + +// +// nsASXULWindowEnumerator +// + +nsASXULWindowEnumerator::nsASXULWindowEnumerator( + const char16_t* aTypeString, + nsWindowMediator& aMediator) : + nsAppShellWindowEnumerator(aTypeString, aMediator) +{ +} + +nsASXULWindowEnumerator::~nsASXULWindowEnumerator() +{ +} + +NS_IMETHODIMP nsASXULWindowEnumerator::GetNext(nsISupports **retval) +{ + if (!retval) + return NS_ERROR_INVALID_ARG; + + *retval = nullptr; + if (mCurrentPosition) { + CallQueryInterface(mCurrentPosition->mWindow, retval); + mCurrentPosition = FindNext(); + } + return NS_OK; +} + +// +// nsASDOMWindowEarlyToLateEnumerator +// + +nsASDOMWindowEarlyToLateEnumerator::nsASDOMWindowEarlyToLateEnumerator( + const char16_t *aTypeString, + nsWindowMediator &aMediator) : + nsASDOMWindowEnumerator(aTypeString, aMediator) +{ + mCurrentPosition = aMediator.mOldestWindow; + AdjustInitialPosition(); +} + +nsASDOMWindowEarlyToLateEnumerator::~nsASDOMWindowEarlyToLateEnumerator() +{ +} + +nsWindowInfo *nsASDOMWindowEarlyToLateEnumerator::FindNext() +{ + nsWindowInfo *info, + *listEnd; + bool allWindows = mType.IsEmpty(); + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return nullptr; + + info = mCurrentPosition->mYounger; + listEnd = mWindowMediator->mOldestWindow; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mYounger; + } + + return nullptr; +} + +// +// nsASXULWindowEarlyToLateEnumerator +// + +nsASXULWindowEarlyToLateEnumerator::nsASXULWindowEarlyToLateEnumerator( + const char16_t *aTypeString, + nsWindowMediator &aMediator) : + nsASXULWindowEnumerator(aTypeString, aMediator) +{ + mCurrentPosition = aMediator.mOldestWindow; + AdjustInitialPosition(); +} + +nsASXULWindowEarlyToLateEnumerator::~nsASXULWindowEarlyToLateEnumerator() +{ +} + +nsWindowInfo *nsASXULWindowEarlyToLateEnumerator::FindNext() +{ + nsWindowInfo *info, + *listEnd; + bool allWindows = mType.IsEmpty(); + + /* mCurrentPosition null is assumed to mean that the enumerator has run + its course and is now basically useless. It could also be interpreted + to mean that it was created at a time when there were no windows. In + that case it would probably be more appropriate to check to see whether + windows have subsequently been added. But it's not guaranteed that we'll + pick up newly added windows anyway (if they occurred previous to our + current position) so we just don't worry about that. */ + if (!mCurrentPosition) + return nullptr; + + info = mCurrentPosition->mYounger; + listEnd = mWindowMediator->mOldestWindow; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mYounger; + } + + return nullptr; +} + +// +// nsASDOMWindowFrontToBackEnumerator +// + +nsASDOMWindowFrontToBackEnumerator::nsASDOMWindowFrontToBackEnumerator( + const char16_t *aTypeString, + nsWindowMediator &aMediator) : + nsASDOMWindowEnumerator(aTypeString, aMediator) +{ + mCurrentPosition = aMediator.mTopmostWindow; + AdjustInitialPosition(); +} + +nsASDOMWindowFrontToBackEnumerator::~nsASDOMWindowFrontToBackEnumerator() +{ +} + +nsWindowInfo *nsASDOMWindowFrontToBackEnumerator::FindNext() +{ + nsWindowInfo *info, + *listEnd; + bool allWindows = mType.IsEmpty(); + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return nullptr; + + info = mCurrentPosition->mLower; + listEnd = mWindowMediator->mTopmostWindow; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mLower; + } + + return nullptr; +} + +// +// nsASXULWindowFrontToBackEnumerator +// + +nsASXULWindowFrontToBackEnumerator::nsASXULWindowFrontToBackEnumerator( + const char16_t *aTypeString, + nsWindowMediator &aMediator) : + nsASXULWindowEnumerator(aTypeString, aMediator) +{ + mCurrentPosition = aMediator.mTopmostWindow; + AdjustInitialPosition(); +} + +nsASXULWindowFrontToBackEnumerator::~nsASXULWindowFrontToBackEnumerator() +{ +} + +nsWindowInfo *nsASXULWindowFrontToBackEnumerator::FindNext() +{ + nsWindowInfo *info, + *listEnd; + bool allWindows = mType.IsEmpty(); + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return nullptr; + + info = mCurrentPosition->mLower; + listEnd = mWindowMediator->mTopmostWindow; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mLower; + } + + return nullptr; +} + +// +// nsASDOMWindowBackToFrontEnumerator +// + +nsASDOMWindowBackToFrontEnumerator::nsASDOMWindowBackToFrontEnumerator( + const char16_t *aTypeString, + nsWindowMediator &aMediator) : + nsASDOMWindowEnumerator(aTypeString, aMediator) +{ + mCurrentPosition = aMediator.mTopmostWindow ? + aMediator.mTopmostWindow->mHigher : nullptr; + AdjustInitialPosition(); +} + +nsASDOMWindowBackToFrontEnumerator::~nsASDOMWindowBackToFrontEnumerator() +{ +} + +nsWindowInfo *nsASDOMWindowBackToFrontEnumerator::FindNext() +{ + nsWindowInfo *info, + *listEnd; + bool allWindows = mType.IsEmpty(); + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return nullptr; + + info = mCurrentPosition->mHigher; + listEnd = mWindowMediator->mTopmostWindow; + if (listEnd) + listEnd = listEnd->mHigher; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mHigher; + } + + return nullptr; +} + +// +// nsASXULWindowBackToFrontEnumerator +// + +nsASXULWindowBackToFrontEnumerator::nsASXULWindowBackToFrontEnumerator( + const char16_t *aTypeString, + nsWindowMediator &aMediator) : + nsASXULWindowEnumerator(aTypeString, aMediator) +{ + mCurrentPosition = aMediator.mTopmostWindow ? + aMediator.mTopmostWindow->mHigher : nullptr; + AdjustInitialPosition(); +} + +nsASXULWindowBackToFrontEnumerator::~nsASXULWindowBackToFrontEnumerator() +{ +} + +nsWindowInfo *nsASXULWindowBackToFrontEnumerator::FindNext() +{ + nsWindowInfo *info, + *listEnd; + bool allWindows = mType.IsEmpty(); + + // see nsXULWindowEarlyToLateEnumerator::FindNext + if (!mCurrentPosition) + return nullptr; + + info = mCurrentPosition->mHigher; + listEnd = mWindowMediator->mTopmostWindow; + if (listEnd) + listEnd = listEnd->mHigher; + + while (info != listEnd) { + if (allWindows || info->TypeEquals(mType)) + return info; + info = info->mHigher; + } + + return nullptr; +} diff --git a/xpfe/appshell/nsAppShellWindowEnumerator.h b/xpfe/appshell/nsAppShellWindowEnumerator.h new file mode 100644 index 000000000..f9a8a2d52 --- /dev/null +++ b/xpfe/appshell/nsAppShellWindowEnumerator.h @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsAppShellWindowEnumerator_h +#define nsAppShellWindowEnumerator_h + +#include "nsCOMPtr.h" +#include "nsString.h" + +#include "nsISimpleEnumerator.h" +#include "nsIXULWindow.h" + +class nsWindowMediator; + +// +// nsWindowInfo +// + +struct nsWindowInfo +{ + nsWindowInfo(nsIXULWindow* inWindow, int32_t inTimeStamp); + ~nsWindowInfo(); + + nsCOMPtr mWindow; + int32_t mTimeStamp; + uint32_t mZLevel; + + // each struct is in two, independent, circular, doubly-linked lists + nsWindowInfo *mYounger, // next younger in sequence + *mOlder; + nsWindowInfo *mLower, // next lower in z-order + *mHigher; + + bool TypeEquals(const nsAString &aType); + void InsertAfter(nsWindowInfo *inOlder, nsWindowInfo *inHigher); + void Unlink(bool inAge, bool inZ); + void ReferenceSelf(bool inAge, bool inZ); +}; + +// +// virtual enumerators +// + +class nsAppShellWindowEnumerator : public nsISimpleEnumerator { + +friend class nsWindowMediator; + +public: + nsAppShellWindowEnumerator(const char16_t* aTypeString, + nsWindowMediator& inMediator); + NS_IMETHOD GetNext(nsISupports **retval) override = 0; + NS_IMETHOD HasMoreElements(bool *retval) override; + + NS_DECL_ISUPPORTS + +protected: + + virtual ~nsAppShellWindowEnumerator(); + + void AdjustInitialPosition(); + virtual nsWindowInfo *FindNext() = 0; + + void WindowRemoved(nsWindowInfo *inInfo); + + nsWindowMediator *mWindowMediator; + nsString mType; + nsWindowInfo *mCurrentPosition; +}; + +class nsASDOMWindowEnumerator : public nsAppShellWindowEnumerator { + +public: + nsASDOMWindowEnumerator(const char16_t* aTypeString, + nsWindowMediator& inMediator); + virtual ~nsASDOMWindowEnumerator(); + NS_IMETHOD GetNext(nsISupports **retval); +}; + +class nsASXULWindowEnumerator : public nsAppShellWindowEnumerator { + +public: + nsASXULWindowEnumerator(const char16_t* aTypeString, + nsWindowMediator& inMediator); + virtual ~nsASXULWindowEnumerator(); + NS_IMETHOD GetNext(nsISupports **retval); +}; + +// +// concrete enumerators +// + +class nsASDOMWindowEarlyToLateEnumerator : public nsASDOMWindowEnumerator { + +public: + nsASDOMWindowEarlyToLateEnumerator(const char16_t* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASDOMWindowEarlyToLateEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASXULWindowEarlyToLateEnumerator : public nsASXULWindowEnumerator { + +public: + nsASXULWindowEarlyToLateEnumerator(const char16_t* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASXULWindowEarlyToLateEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASDOMWindowFrontToBackEnumerator : public nsASDOMWindowEnumerator { + +public: + nsASDOMWindowFrontToBackEnumerator(const char16_t* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASDOMWindowFrontToBackEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASXULWindowFrontToBackEnumerator : public nsASXULWindowEnumerator { + +public: + nsASXULWindowFrontToBackEnumerator(const char16_t* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASXULWindowFrontToBackEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASDOMWindowBackToFrontEnumerator : public nsASDOMWindowEnumerator { + +public: + nsASDOMWindowBackToFrontEnumerator(const char16_t* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASDOMWindowBackToFrontEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +class nsASXULWindowBackToFrontEnumerator : public nsASXULWindowEnumerator { + +public: + nsASXULWindowBackToFrontEnumerator(const char16_t* aTypeString, + nsWindowMediator& inMediator); + + virtual ~nsASXULWindowBackToFrontEnumerator(); + +protected: + virtual nsWindowInfo *FindNext(); +}; + +#endif diff --git a/xpfe/appshell/nsChromeTreeOwner.cpp b/xpfe/appshell/nsChromeTreeOwner.cpp new file mode 100644 index 000000000..63fa86373 --- /dev/null +++ b/xpfe/appshell/nsChromeTreeOwner.cpp @@ -0,0 +1,561 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Local Includes +#include "nsChromeTreeOwner.h" +#include "nsXULWindow.h" + +// Helper Classes +#include "nsString.h" +#include "nsIEmbeddingSiteWindow.h" +#include "nsIServiceManager.h" +#include "nsIDocShellTreeItem.h" + +// Interfaces needed to include +#include "nsIPrompt.h" +#include "nsIAuthPrompt.h" +#include "nsIBrowserDOMWindow.h" +#include "nsIWebProgress.h" +#include "nsIWidget.h" +#include "nsIWindowMediator.h" +#include "nsIDOMChromeWindow.h" +#include "nsIDOMNode.h" +#include "nsIDOMElement.h" +#include "nsIDOMNodeList.h" +#include "nsIDOMXULElement.h" +#include "nsIXULBrowserWindow.h" +#include "mozilla/dom/Element.h" + +using namespace mozilla; + +//***************************************************************************** +// nsChromeTreeOwner string literals +//***************************************************************************** + +struct nsChromeTreeOwnerLiterals +{ + const nsLiteralString kPersist; + const nsLiteralString kScreenX; + const nsLiteralString kScreenY; + const nsLiteralString kWidth; + const nsLiteralString kHeight; + const nsLiteralString kSizemode; + const nsLiteralString kSpace; + + nsChromeTreeOwnerLiterals() + : NS_LITERAL_STRING_INIT(kPersist,"persist") + , NS_LITERAL_STRING_INIT(kScreenX,"screenX") + , NS_LITERAL_STRING_INIT(kScreenY,"screenY") + , NS_LITERAL_STRING_INIT(kWidth,"width") + , NS_LITERAL_STRING_INIT(kHeight,"height") + , NS_LITERAL_STRING_INIT(kSizemode,"sizemode") + , NS_LITERAL_STRING_INIT(kSpace," ") + {} +}; + +static nsChromeTreeOwnerLiterals *gLiterals; + +nsresult +nsChromeTreeOwner::InitGlobals() +{ + NS_ASSERTION(gLiterals == nullptr, "already initialized"); + gLiterals = new nsChromeTreeOwnerLiterals(); + return NS_OK; +} + +void +nsChromeTreeOwner::FreeGlobals() +{ + delete gLiterals; + gLiterals = nullptr; +} + +//***************************************************************************** +//*** nsChromeTreeOwner: Object Management +//***************************************************************************** + +nsChromeTreeOwner::nsChromeTreeOwner() : mXULWindow(nullptr) +{ +} + +nsChromeTreeOwner::~nsChromeTreeOwner() +{ +} + +//***************************************************************************** +// nsChromeTreeOwner::nsISupports +//***************************************************************************** + +NS_IMPL_ADDREF(nsChromeTreeOwner) +NS_IMPL_RELEASE(nsChromeTreeOwner) + +NS_INTERFACE_MAP_BEGIN(nsChromeTreeOwner) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) + NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) +NS_INTERFACE_MAP_END + +//***************************************************************************** +// nsChromeTreeOwner::nsIInterfaceRequestor +//***************************************************************************** + +NS_IMETHODIMP nsChromeTreeOwner::GetInterface(const nsIID& aIID, void** aSink) +{ + NS_ENSURE_ARG_POINTER(aSink); + + if(aIID.Equals(NS_GET_IID(nsIPrompt))) { + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetInterface(aIID, aSink); + } + if(aIID.Equals(NS_GET_IID(nsIAuthPrompt))) { + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetInterface(aIID, aSink); + } + if(aIID.Equals(NS_GET_IID(nsIWebBrowserChrome))) { + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetInterface(aIID, aSink); + } + if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow))) { + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetInterface(aIID, aSink); + } + if (aIID.Equals(NS_GET_IID(nsIXULWindow))) { + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->QueryInterface(aIID, aSink); + } + + return QueryInterface(aIID, aSink); +} + +//***************************************************************************** +// nsChromeTreeOwner::nsIDocShellTreeOwner +//***************************************************************************** + +NS_IMETHODIMP +nsChromeTreeOwner::ContentShellAdded(nsIDocShellTreeItem* aContentShell, + bool aPrimary, bool aTargetable, + const nsAString& aID) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->ContentShellAdded(aContentShell, aPrimary, aTargetable, + aID); +} + +NS_IMETHODIMP +nsChromeTreeOwner::ContentShellRemoved(nsIDocShellTreeItem* aContentShell) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->ContentShellRemoved(aContentShell); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetPrimaryContentShell(nsIDocShellTreeItem** aShell) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPrimaryContentShell(aShell); +} + +NS_IMETHODIMP +nsChromeTreeOwner::TabParentAdded(nsITabParent* aTab, bool aPrimary) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->TabParentAdded(aTab, aPrimary); +} + +NS_IMETHODIMP +nsChromeTreeOwner::TabParentRemoved(nsITabParent* aTab) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->TabParentRemoved(aTab); +} + +NS_IMETHODIMP +nsChromeTreeOwner::GetPrimaryTabParent(nsITabParent** aTab) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPrimaryTabParent(aTab); +} + +NS_IMETHODIMP +nsChromeTreeOwner::GetPrimaryContentSize(int32_t* aWidth, + int32_t* aHeight) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPrimaryContentSize(aWidth, aHeight); +} + +NS_IMETHODIMP +nsChromeTreeOwner::SetPrimaryContentSize(int32_t aWidth, + int32_t aHeight) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetPrimaryContentSize(aWidth, aHeight); +} + +NS_IMETHODIMP +nsChromeTreeOwner::GetRootShellSize(int32_t* aWidth, + int32_t* aHeight) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetRootShellSize(aWidth, aHeight); +} + +NS_IMETHODIMP +nsChromeTreeOwner::SetRootShellSize(int32_t aWidth, + int32_t aHeight) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetRootShellSize(aWidth, aHeight); +} + +NS_IMETHODIMP nsChromeTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem, + int32_t aCX, int32_t aCY) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SizeShellTo(aShellItem, aCX, aCY); +} + +NS_IMETHODIMP +nsChromeTreeOwner::SetPersistence(bool aPersistPosition, + bool aPersistSize, + bool aPersistSizeMode) +{ + NS_ENSURE_STATE(mXULWindow); + nsCOMPtr docShellElement = mXULWindow->GetWindowDOMElement(); + if (!docShellElement) + return NS_ERROR_FAILURE; + + nsAutoString persistString; + docShellElement->GetAttribute(gLiterals->kPersist, persistString); + + bool saveString = false; + int32_t index; + +#define FIND_PERSIST_STRING(aString, aCond) \ + index = persistString.Find(aString); \ + if (!aCond && index > kNotFound) { \ + persistString.Cut(index, aString.Length()); \ + saveString = true; \ + } else if (aCond && index == kNotFound) { \ + persistString.Append(gLiterals->kSpace + aString); \ + saveString = true; \ + } + FIND_PERSIST_STRING(gLiterals->kScreenX, aPersistPosition); + FIND_PERSIST_STRING(gLiterals->kScreenY, aPersistPosition); + FIND_PERSIST_STRING(gLiterals->kWidth, aPersistSize); + FIND_PERSIST_STRING(gLiterals->kHeight, aPersistSize); + FIND_PERSIST_STRING(gLiterals->kSizemode, aPersistSizeMode); + + ErrorResult rv; + if (saveString) { + docShellElement->SetAttribute(gLiterals->kPersist, persistString, rv); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsChromeTreeOwner::GetPersistence(bool* aPersistPosition, + bool* aPersistSize, + bool* aPersistSizeMode) +{ + NS_ENSURE_STATE(mXULWindow); + nsCOMPtr docShellElement = mXULWindow->GetWindowDOMElement(); + if (!docShellElement) + return NS_ERROR_FAILURE; + + nsAutoString persistString; + docShellElement->GetAttribute(gLiterals->kPersist, persistString); + + // data structure doesn't quite match the question, but it's close enough + // for what we want (since this method is never actually called...) + if (aPersistPosition) + *aPersistPosition = persistString.Find(gLiterals->kScreenX) > kNotFound || + persistString.Find(gLiterals->kScreenY) > kNotFound; + if (aPersistSize) + *aPersistSize = persistString.Find(gLiterals->kWidth) > kNotFound || + persistString.Find(gLiterals->kHeight) > kNotFound; + if (aPersistSizeMode) + *aPersistSizeMode = persistString.Find(gLiterals->kSizemode) > kNotFound; + + return NS_OK; +} + +NS_IMETHODIMP +nsChromeTreeOwner::GetTargetableShellCount(uint32_t* aResult) +{ + *aResult = 0; + return NS_OK; +} + +NS_IMETHODIMP +nsChromeTreeOwner::GetHasPrimaryContent(bool* aResult) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetHasPrimaryContent(aResult); +} + +//***************************************************************************** +// nsChromeTreeOwner::nsIBaseWindow +//***************************************************************************** + +NS_IMETHODIMP nsChromeTreeOwner::InitWindow(nativeWindow aParentNativeWindow, + nsIWidget* parentWidget, int32_t x, int32_t y, int32_t cx, int32_t cy) +{ + // Ignore widget parents for now. Don't think those are a vaild thing to call. + NS_ENSURE_SUCCESS(SetPositionAndSize(x, y, cx, cy, 0), NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP nsChromeTreeOwner::Create() +{ + NS_ASSERTION(false, "You can't call this"); + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP nsChromeTreeOwner::Destroy() +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->Destroy(); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetUnscaledDevicePixelsPerCSSPixel(double *aScale) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetUnscaledDevicePixelsPerCSSPixel(aScale); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetDevicePixelsPerDesktopPixel(double *aScale) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetDevicePixelsPerDesktopPixel(aScale); +} + +NS_IMETHODIMP nsChromeTreeOwner::SetPositionDesktopPix(int32_t x, int32_t y) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetPositionDesktopPix(x, y); +} + +NS_IMETHODIMP nsChromeTreeOwner::SetPosition(int32_t x, int32_t y) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetPosition(x, y); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetPosition(int32_t* x, int32_t* y) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPosition(x, y); +} + +NS_IMETHODIMP nsChromeTreeOwner::SetSize(int32_t cx, int32_t cy, bool fRepaint) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetSize(cx, cy, fRepaint); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetSize(int32_t* cx, int32_t* cy) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetSize(cx, cy); +} + +NS_IMETHODIMP nsChromeTreeOwner::SetPositionAndSize(int32_t x, int32_t y, int32_t cx, + int32_t cy, uint32_t aFlags) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetPositionAndSize(x, y, cx, cy, aFlags); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetPositionAndSize(int32_t* x, int32_t* y, int32_t* cx, + int32_t* cy) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPositionAndSize(x, y, cx, cy); +} + +NS_IMETHODIMP nsChromeTreeOwner::Repaint(bool aForce) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->Repaint(aForce); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetParentWidget(nsIWidget** aParentWidget) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetParentWidget(aParentWidget); +} + +NS_IMETHODIMP nsChromeTreeOwner::SetParentWidget(nsIWidget* aParentWidget) +{ + NS_ASSERTION(false, "You can't call this"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsChromeTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetParentNativeWindow(aParentNativeWindow); +} + +NS_IMETHODIMP nsChromeTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow) +{ + NS_ASSERTION(false, "You can't call this"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsChromeTreeOwner::GetNativeHandle(nsAString& aNativeHandle) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetNativeHandle(aNativeHandle); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetVisibility(bool* aVisibility) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetVisibility(aVisibility); +} + +NS_IMETHODIMP nsChromeTreeOwner::SetVisibility(bool aVisibility) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetVisibility(aVisibility); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetEnabled(bool *aEnabled) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetEnabled(aEnabled); +} + +NS_IMETHODIMP nsChromeTreeOwner::SetEnabled(bool aEnable) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetEnabled(aEnable); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetMainWidget(nsIWidget** aMainWidget) +{ + NS_ENSURE_ARG_POINTER(aMainWidget); + NS_ENSURE_STATE(mXULWindow); + + *aMainWidget = mXULWindow->mWindow; + NS_IF_ADDREF(*aMainWidget); + + return NS_OK; +} + +NS_IMETHODIMP nsChromeTreeOwner::SetFocus() +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetFocus(); +} + +NS_IMETHODIMP nsChromeTreeOwner::GetTitle(char16_t** aTitle) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetTitle(aTitle); +} + +NS_IMETHODIMP nsChromeTreeOwner::SetTitle(const char16_t* aTitle) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetTitle(aTitle); +} + +//***************************************************************************** +// nsChromeTreeOwner::nsIWebProgressListener +//***************************************************************************** + +NS_IMETHODIMP +nsChromeTreeOwner::OnProgressChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + int32_t aCurSelfProgress, + int32_t aMaxSelfProgress, + int32_t aCurTotalProgress, + int32_t aMaxTotalProgress) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsChromeTreeOwner::OnStateChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + uint32_t aProgressStateFlags, + nsresult aStatus) +{ + return NS_OK; +} + +NS_IMETHODIMP nsChromeTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsIURI* aLocation, + uint32_t aFlags) +{ + bool itsForYou = true; + + if (aWebProgress) { + NS_ENSURE_STATE(mXULWindow); + nsCOMPtr progressWin; + aWebProgress->GetDOMWindow(getter_AddRefs(progressWin)); + + nsCOMPtr docshell; + mXULWindow->GetDocShell(getter_AddRefs(docshell)); + // XXXkhuey this is totally wrong, bug 1223303. + nsCOMPtr ourWin(do_QueryInterface(docshell)); + + if (ourWin != progressWin) + itsForYou = false; + } + + // If loading a new root .xul document, then redo chrome. + if (itsForYou) { + NS_ENSURE_STATE(mXULWindow); + mXULWindow->mChromeLoaded = false; + } + return NS_OK; +} + +NS_IMETHODIMP +nsChromeTreeOwner::OnStatusChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsresult aStatus, + const char16_t* aMessage) +{ + return NS_OK; +} + + + +NS_IMETHODIMP +nsChromeTreeOwner::OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + uint32_t state) +{ + return NS_OK; +} + +//***************************************************************************** +// nsChromeTreeOwner: Helpers +//***************************************************************************** + +//***************************************************************************** +// nsChromeTreeOwner: Accessors +//***************************************************************************** + +void nsChromeTreeOwner::XULWindow(nsXULWindow* aXULWindow) +{ + mXULWindow = aXULWindow; +} + +nsXULWindow* nsChromeTreeOwner::XULWindow() +{ + return mXULWindow; +} diff --git a/xpfe/appshell/nsChromeTreeOwner.h b/xpfe/appshell/nsChromeTreeOwner.h new file mode 100644 index 000000000..77b0dea89 --- /dev/null +++ b/xpfe/appshell/nsChromeTreeOwner.h @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsChromeTreeOwner_h__ +#define nsChromeTreeOwner_h__ + +// Helper Classes +#include "nsCOMPtr.h" + +// Interfaces Needed +#include "nsIBaseWindow.h" +#include "nsIDocShellTreeOwner.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIWebProgressListener.h" +#include "nsWeakReference.h" + +class nsXULWindow; + +class nsChromeTreeOwner : public nsIDocShellTreeOwner, + public nsIBaseWindow, + public nsIInterfaceRequestor, + public nsIWebProgressListener, + public nsSupportsWeakReference +{ +friend class nsXULWindow; + +public: + NS_DECL_ISUPPORTS + + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSIBASEWINDOW + NS_DECL_NSIDOCSHELLTREEOWNER + NS_DECL_NSIWEBPROGRESSLISTENER + + static nsresult InitGlobals(); + static void FreeGlobals(); + +protected: + nsChromeTreeOwner(); + virtual ~nsChromeTreeOwner(); + + void XULWindow(nsXULWindow* aXULWindow); + nsXULWindow* XULWindow(); + +protected: + nsXULWindow* mXULWindow; +}; + +#endif /* nsChromeTreeOwner_h__ */ diff --git a/xpfe/appshell/nsContentTreeOwner.cpp b/xpfe/appshell/nsContentTreeOwner.cpp new file mode 100644 index 000000000..b39b7610f --- /dev/null +++ b/xpfe/appshell/nsContentTreeOwner.cpp @@ -0,0 +1,1131 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=2 sw=2 et tw=79: + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Local Includes +#include "nsContentTreeOwner.h" +#include "nsXULWindow.h" + +// Helper Classes +#include "nsIServiceManager.h" +#include "nsAutoPtr.h" + +// Interfaces needed to be included +#include "nsIDOMNode.h" +#include "nsIDOMElement.h" +#include "nsIDOMNodeList.h" +#include "nsIDOMWindow.h" +#include "nsIDOMChromeWindow.h" +#include "nsIBrowserDOMWindow.h" +#include "nsIDOMXULElement.h" +#include "nsIEmbeddingSiteWindow.h" +#include "nsIPrompt.h" +#include "nsIAuthPrompt.h" +#include "nsIWindowMediator.h" +#include "nsIXULBrowserWindow.h" +#include "nsIPrincipal.h" +#include "nsIURIFixup.h" +#include "nsCDefaultURIFixup.h" +#include "nsIWebNavigation.h" +#include "nsDocShellCID.h" +#include "nsIExternalURLHandlerService.h" +#include "nsIMIMEInfo.h" +#include "nsIWidget.h" +#include "nsWindowWatcher.h" +#include "mozilla/BrowserElementParent.h" + +#include "nsIDOMDocument.h" +#include "nsIScriptObjectPrincipal.h" +#include "nsIURI.h" +#include "nsIDocument.h" +#if defined(XP_MACOSX) +#include "nsThreadUtils.h" +#endif + +#include "mozilla/Preferences.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/ScriptSettings.h" + +using namespace mozilla; + +//***************************************************************************** +//*** nsSiteWindow declaration +//***************************************************************************** + +class nsSiteWindow : public nsIEmbeddingSiteWindow +{ + // nsSiteWindow shares a lifetime with nsContentTreeOwner, and proxies it's + // AddRef and Release calls to said object. + // When nsContentTreeOwner is destroyed, nsSiteWindow will be destroyed as well. + // nsContentTreeOwner is a friend class of nsSiteWindow such that it can call + // nsSiteWindow's destructor, which is private, as public destructors + // on reference counted classes are generally unsafe. + friend class nsContentTreeOwner; + +public: + explicit nsSiteWindow(nsContentTreeOwner *aAggregator); + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIEMBEDDINGSITEWINDOW + +private: + virtual ~nsSiteWindow(); + nsContentTreeOwner *mAggregator; +}; + +//***************************************************************************** +//*** nsContentTreeOwner: Object Management +//***************************************************************************** + +nsContentTreeOwner::nsContentTreeOwner(bool fPrimary) : mXULWindow(nullptr), + mPrimary(fPrimary), mContentTitleSetting(false) +{ + // note if this fails, QI on nsIEmbeddingSiteWindow(2) will simply fail + mSiteWindow = new nsSiteWindow(this); +} + +nsContentTreeOwner::~nsContentTreeOwner() +{ + delete mSiteWindow; +} + +//***************************************************************************** +// nsContentTreeOwner::nsISupports +//***************************************************************************** + +NS_IMPL_ADDREF(nsContentTreeOwner) +NS_IMPL_RELEASE(nsContentTreeOwner) + +NS_INTERFACE_MAP_BEGIN(nsContentTreeOwner) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome3) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) + // NOTE: This is using aggregation because there are some properties and + // method on nsIBaseWindow (which we implement) and on + // nsIEmbeddingSiteWindow (which we also implement) that have the same name. + // And it just so happens that we want different behavior for these methods + // and properties depending on the interface through which they're called + // (SetFocus() is a good example here). If it were not for that, we could + // ditch the aggregation and just deal with not being able to use NS_DECL_* + // macros for this stuff.... + NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIEmbeddingSiteWindow, mSiteWindow) +NS_INTERFACE_MAP_END + +//***************************************************************************** +// nsContentTreeOwner::nsIInterfaceRequestor +//***************************************************************************** + +NS_IMETHODIMP nsContentTreeOwner::GetInterface(const nsIID& aIID, void** aSink) +{ + NS_ENSURE_ARG_POINTER(aSink); + *aSink = 0; + + if(aIID.Equals(NS_GET_IID(nsIPrompt))) { + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetInterface(aIID, aSink); + } + if(aIID.Equals(NS_GET_IID(nsIAuthPrompt))) { + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetInterface(aIID, aSink); + } + if (aIID.Equals(NS_GET_IID(nsIDocShellTreeItem))) { + NS_ENSURE_STATE(mXULWindow); + nsCOMPtr shell; + mXULWindow->GetDocShell(getter_AddRefs(shell)); + if (shell) + return shell->QueryInterface(aIID, aSink); + return NS_ERROR_FAILURE; + } + + if (aIID.Equals(NS_GET_IID(nsIDOMWindow)) || + aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter))) { + NS_ENSURE_STATE(mXULWindow); + nsCOMPtr shell; + mXULWindow->GetPrimaryContentShell(getter_AddRefs(shell)); + if (shell) { + nsCOMPtr thing(do_QueryInterface(shell)); + if (thing) + return thing->GetInterface(aIID, aSink); + } + return NS_ERROR_FAILURE; + } + + if (aIID.Equals(NS_GET_IID(nsIXULWindow))) { + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->QueryInterface(aIID, aSink); + } + + return QueryInterface(aIID, aSink); +} + +//***************************************************************************** +// nsContentTreeOwner::nsIDocShellTreeOwner +//***************************************************************************** + +NS_IMETHODIMP +nsContentTreeOwner::ContentShellAdded(nsIDocShellTreeItem* aContentShell, + bool aPrimary, bool aTargetable, + const nsAString& aID) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->ContentShellAdded(aContentShell, aPrimary, aTargetable, + aID); +} + +NS_IMETHODIMP +nsContentTreeOwner::ContentShellRemoved(nsIDocShellTreeItem* aContentShell) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->ContentShellRemoved(aContentShell); +} + +NS_IMETHODIMP +nsContentTreeOwner::GetPrimaryContentShell(nsIDocShellTreeItem** aShell) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPrimaryContentShell(aShell); +} + +NS_IMETHODIMP +nsContentTreeOwner::TabParentAdded(nsITabParent* aTab, bool aPrimary) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->TabParentAdded(aTab, aPrimary); +} + +NS_IMETHODIMP +nsContentTreeOwner::TabParentRemoved(nsITabParent* aTab) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->TabParentRemoved(aTab); +} + +NS_IMETHODIMP +nsContentTreeOwner::GetPrimaryTabParent(nsITabParent** aTab) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPrimaryTabParent(aTab); +} + +NS_IMETHODIMP +nsContentTreeOwner::GetPrimaryContentSize(int32_t* aWidth, + int32_t* aHeight) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPrimaryContentSize(aWidth, aHeight); +} + +NS_IMETHODIMP +nsContentTreeOwner::SetPrimaryContentSize(int32_t aWidth, + int32_t aHeight) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetPrimaryContentSize(aWidth, aHeight); +} + +NS_IMETHODIMP +nsContentTreeOwner::GetRootShellSize(int32_t* aWidth, + int32_t* aHeight) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetRootShellSize(aWidth, aHeight); +} + +NS_IMETHODIMP +nsContentTreeOwner::SetRootShellSize(int32_t aWidth, + int32_t aHeight) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetRootShellSize(aWidth, aHeight); +} + +NS_IMETHODIMP nsContentTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem, + int32_t aCX, int32_t aCY) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SizeShellTo(aShellItem, aCX, aCY); +} + +NS_IMETHODIMP +nsContentTreeOwner::SetPersistence(bool aPersistPosition, + bool aPersistSize, + bool aPersistSizeMode) +{ + NS_ENSURE_STATE(mXULWindow); + nsCOMPtr docShellElement = mXULWindow->GetWindowDOMElement(); + if (!docShellElement) + return NS_ERROR_FAILURE; + + nsAutoString persistString; + docShellElement->GetAttribute(NS_LITERAL_STRING("persist"), persistString); + + bool saveString = false; + int32_t index; + + // Set X + index = persistString.Find("screenX"); + if (!aPersistPosition && index >= 0) { + persistString.Cut(index, 7); + saveString = true; + } else if (aPersistPosition && index < 0) { + persistString.AppendLiteral(" screenX"); + saveString = true; + } + // Set Y + index = persistString.Find("screenY"); + if (!aPersistPosition && index >= 0) { + persistString.Cut(index, 7); + saveString = true; + } else if (aPersistPosition && index < 0) { + persistString.AppendLiteral(" screenY"); + saveString = true; + } + // Set CX + index = persistString.Find("width"); + if (!aPersistSize && index >= 0) { + persistString.Cut(index, 5); + saveString = true; + } else if (aPersistSize && index < 0) { + persistString.AppendLiteral(" width"); + saveString = true; + } + // Set CY + index = persistString.Find("height"); + if (!aPersistSize && index >= 0) { + persistString.Cut(index, 6); + saveString = true; + } else if (aPersistSize && index < 0) { + persistString.AppendLiteral(" height"); + saveString = true; + } + // Set SizeMode + index = persistString.Find("sizemode"); + if (!aPersistSizeMode && (index >= 0)) { + persistString.Cut(index, 8); + saveString = true; + } else if (aPersistSizeMode && (index < 0)) { + persistString.AppendLiteral(" sizemode"); + saveString = true; + } + + ErrorResult rv; + if(saveString) { + docShellElement->SetAttribute(NS_LITERAL_STRING("persist"), persistString, rv); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsContentTreeOwner::GetPersistence(bool* aPersistPosition, + bool* aPersistSize, + bool* aPersistSizeMode) +{ + NS_ENSURE_STATE(mXULWindow); + nsCOMPtr docShellElement = mXULWindow->GetWindowDOMElement(); + if (!docShellElement) + return NS_ERROR_FAILURE; + + nsAutoString persistString; + docShellElement->GetAttribute(NS_LITERAL_STRING("persist"), persistString); + + // data structure doesn't quite match the question, but it's close enough + // for what we want (since this method is never actually called...) + if (aPersistPosition) + *aPersistPosition = persistString.Find("screenX") >= 0 || persistString.Find("screenY") >= 0 ? true : false; + if (aPersistSize) + *aPersistSize = persistString.Find("width") >= 0 || persistString.Find("height") >= 0 ? true : false; + if (aPersistSizeMode) + *aPersistSizeMode = persistString.Find("sizemode") >= 0 ? true : false; + + return NS_OK; +} + +NS_IMETHODIMP +nsContentTreeOwner::GetTargetableShellCount(uint32_t* aResult) +{ + NS_ENSURE_STATE(mXULWindow); + *aResult = mXULWindow->mTargetableShells.Count(); + return NS_OK; +} + +NS_IMETHODIMP +nsContentTreeOwner::GetHasPrimaryContent(bool* aResult) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetHasPrimaryContent(aResult); +} + +//***************************************************************************** +// nsContentTreeOwner::nsIWebBrowserChrome3 +//***************************************************************************** + +NS_IMETHODIMP nsContentTreeOwner::OnBeforeLinkTraversal(const nsAString &originalTarget, + nsIURI *linkURI, + nsIDOMNode *linkNode, + bool isAppTab, + nsAString &_retval) +{ + NS_ENSURE_STATE(mXULWindow); + + nsCOMPtr xulBrowserWindow; + mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); + + if (xulBrowserWindow) + return xulBrowserWindow->OnBeforeLinkTraversal(originalTarget, linkURI, + linkNode, isAppTab, _retval); + + _retval = originalTarget; + return NS_OK; +} + +NS_IMETHODIMP nsContentTreeOwner::ShouldLoadURI(nsIDocShell *aDocShell, + nsIURI *aURI, + nsIURI *aReferrer, + bool *_retval) +{ + NS_ENSURE_STATE(mXULWindow); + + nsCOMPtr xulBrowserWindow; + mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); + + if (xulBrowserWindow) + return xulBrowserWindow->ShouldLoadURI(aDocShell, aURI, aReferrer, _retval); + + *_retval = true; + return NS_OK; +} + +NS_IMETHODIMP nsContentTreeOwner::ReloadInFreshProcess(nsIDocShell* aDocShell, + nsIURI* aURI, + nsIURI* aReferrer, + bool* aRetVal) +{ + NS_WARNING("Cannot reload in fresh process from a nsContentTreeOwner!"); + *aRetVal = false; + return NS_OK; +} + +//***************************************************************************** +// nsContentTreeOwner::nsIWebBrowserChrome2 +//***************************************************************************** + +NS_IMETHODIMP nsContentTreeOwner::SetStatusWithContext(uint32_t aStatusType, + const nsAString &aStatusText, + nsISupports *aStatusContext) +{ + // We only allow the status to be set from the primary content shell + if (!mPrimary && aStatusType != STATUS_LINK) + return NS_OK; + + NS_ENSURE_STATE(mXULWindow); + + nsCOMPtr xulBrowserWindow; + mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); + + if (xulBrowserWindow) + { + switch(aStatusType) + { + case STATUS_SCRIPT: + xulBrowserWindow->SetJSStatus(aStatusText); + break; + case STATUS_LINK: + { + nsCOMPtr element = do_QueryInterface(aStatusContext); + xulBrowserWindow->SetOverLink(aStatusText, element); + break; + } + } + } + + return NS_OK; +} + +//***************************************************************************** +// nsContentTreeOwner::nsIWebBrowserChrome +//***************************************************************************** + +NS_IMETHODIMP nsContentTreeOwner::SetStatus(uint32_t aStatusType, + const char16_t* aStatus) +{ + return SetStatusWithContext(aStatusType, + aStatus ? static_cast(nsDependentString(aStatus)) + : EmptyString(), + nullptr); +} + +NS_IMETHODIMP nsContentTreeOwner::SetWebBrowser(nsIWebBrowser* aWebBrowser) +{ + NS_ERROR("Haven't Implemented this yet"); + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsContentTreeOwner::GetWebBrowser(nsIWebBrowser** aWebBrowser) +{ + // Unimplemented, and probably will remain so; xpfe windows have docshells, + // not webbrowsers. + NS_ENSURE_ARG_POINTER(aWebBrowser); + *aWebBrowser = 0; + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsContentTreeOwner::SetChromeFlags(uint32_t aChromeFlags) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetChromeFlags(aChromeFlags); +} + +NS_IMETHODIMP nsContentTreeOwner::GetChromeFlags(uint32_t* aChromeFlags) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetChromeFlags(aChromeFlags); +} + +NS_IMETHODIMP nsContentTreeOwner::DestroyBrowserWindow() +{ + NS_ERROR("Haven't Implemented this yet"); + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsContentTreeOwner::SizeBrowserTo(int32_t aCX, int32_t aCY) +{ + NS_ERROR("Haven't Implemented this yet"); + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsContentTreeOwner::ShowAsModal() +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->ShowModal(); +} + +NS_IMETHODIMP nsContentTreeOwner::IsWindowModal(bool *_retval) +{ + NS_ENSURE_STATE(mXULWindow); + *_retval = mXULWindow->mContinueModalLoop; + return NS_OK; +} + +NS_IMETHODIMP nsContentTreeOwner::ExitModalEventLoop(nsresult aStatus) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->ExitModalLoop(aStatus); +} + +//***************************************************************************** +// nsContentTreeOwner::nsIBaseWindow +//***************************************************************************** + +NS_IMETHODIMP nsContentTreeOwner::InitWindow(nativeWindow aParentNativeWindow, + nsIWidget* parentWidget, int32_t x, int32_t y, int32_t cx, int32_t cy) +{ + // Ignore wigdet parents for now. Don't think those are a vaild thing to call. + NS_ENSURE_SUCCESS(SetPositionAndSize(x, y, cx, cy, 0), NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP nsContentTreeOwner::Create() +{ + NS_ASSERTION(false, "You can't call this"); + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP nsContentTreeOwner::Destroy() +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->Destroy(); +} + +NS_IMETHODIMP nsContentTreeOwner::GetUnscaledDevicePixelsPerCSSPixel(double* aScale) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetUnscaledDevicePixelsPerCSSPixel(aScale); +} + +NS_IMETHODIMP nsContentTreeOwner::GetDevicePixelsPerDesktopPixel(double* aScale) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetDevicePixelsPerDesktopPixel(aScale); +} + +NS_IMETHODIMP nsContentTreeOwner::SetPositionDesktopPix(int32_t aX, int32_t aY) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetPositionDesktopPix(aX, aY); +} + +NS_IMETHODIMP nsContentTreeOwner::SetPosition(int32_t aX, int32_t aY) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetPosition(aX, aY); +} + +NS_IMETHODIMP nsContentTreeOwner::GetPosition(int32_t* aX, int32_t* aY) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPosition(aX, aY); +} + +NS_IMETHODIMP nsContentTreeOwner::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetSize(aCX, aCY, aRepaint); +} + +NS_IMETHODIMP nsContentTreeOwner::GetSize(int32_t* aCX, int32_t* aCY) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetSize(aCX, aCY); +} + +NS_IMETHODIMP nsContentTreeOwner::SetPositionAndSize(int32_t aX, int32_t aY, + int32_t aCX, int32_t aCY, uint32_t aFlags) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetPositionAndSize(aX, aY, aCX, aCY, aFlags); +} + +NS_IMETHODIMP nsContentTreeOwner::GetPositionAndSize(int32_t* aX, int32_t* aY, + int32_t* aCX, int32_t* aCY) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetPositionAndSize(aX, aY, aCX, aCY); +} + +NS_IMETHODIMP nsContentTreeOwner::Repaint(bool aForce) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->Repaint(aForce); +} + +NS_IMETHODIMP nsContentTreeOwner::GetParentWidget(nsIWidget** aParentWidget) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetParentWidget(aParentWidget); +} + +NS_IMETHODIMP nsContentTreeOwner::SetParentWidget(nsIWidget* aParentWidget) +{ + NS_ASSERTION(false, "You can't call this"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsContentTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetParentNativeWindow(aParentNativeWindow); +} + +NS_IMETHODIMP nsContentTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow) +{ + NS_ASSERTION(false, "You can't call this"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsContentTreeOwner::GetNativeHandle(nsAString& aNativeHandle) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetNativeHandle(aNativeHandle); +} + +NS_IMETHODIMP nsContentTreeOwner::GetVisibility(bool* aVisibility) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetVisibility(aVisibility); +} + +NS_IMETHODIMP nsContentTreeOwner::SetVisibility(bool aVisibility) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetVisibility(aVisibility); +} + +NS_IMETHODIMP nsContentTreeOwner::GetEnabled(bool *aEnabled) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->GetEnabled(aEnabled); +} + +NS_IMETHODIMP nsContentTreeOwner::SetEnabled(bool aEnable) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetEnabled(aEnable); +} + +NS_IMETHODIMP nsContentTreeOwner::GetMainWidget(nsIWidget** aMainWidget) +{ + NS_ENSURE_ARG_POINTER(aMainWidget); + NS_ENSURE_STATE(mXULWindow); + + *aMainWidget = mXULWindow->mWindow; + NS_IF_ADDREF(*aMainWidget); + + return NS_OK; +} + +NS_IMETHODIMP nsContentTreeOwner::SetFocus() +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetFocus(); +} + +NS_IMETHODIMP nsContentTreeOwner::GetTitle(char16_t** aTitle) +{ + NS_ENSURE_ARG_POINTER(aTitle); + NS_ENSURE_STATE(mXULWindow); + + return mXULWindow->GetTitle(aTitle); +} + +NS_IMETHODIMP nsContentTreeOwner::SetTitle(const char16_t* aTitle) +{ + // We only allow the title to be set from the primary content shell + if(!mPrimary || !mContentTitleSetting) + return NS_OK; + + NS_ENSURE_STATE(mXULWindow); + + nsAutoString title; + nsAutoString docTitle(aTitle); + + if (docTitle.IsEmpty()) + docTitle.Assign(mTitleDefault); + + if (!docTitle.IsEmpty()) { + if (!mTitlePreface.IsEmpty()) { + // Title will be: "Preface: Doc Title - Mozilla" + title.Assign(mTitlePreface); + title.Append(docTitle); + } + else { + // Title will be: "Doc Title - Mozilla" + title = docTitle; + } + + if (!mWindowTitleModifier.IsEmpty()) + title += mTitleSeparator + mWindowTitleModifier; + } + else + title.Assign(mWindowTitleModifier); // Title will just be plain "Mozilla" + + // + // if there is no location bar we modify the title to display at least + // the scheme and host (if any) as an anti-spoofing measure. + // + nsCOMPtr docShellElement = mXULWindow->GetWindowDOMElement(); + + if (docShellElement) { + nsAutoString chromeString; + docShellElement->GetAttribute(NS_LITERAL_STRING("chromehidden"), chromeString); + if (chromeString.Find(NS_LITERAL_STRING("location")) != kNotFound) { + // + // location bar is turned off, find the browser location + // + // use the document's nsPrincipal to find the true owner + // in case of javascript: or data: documents + // + nsCOMPtr dsitem; + GetPrimaryContentShell(getter_AddRefs(dsitem)); + nsCOMPtr doc = + do_QueryInterface(dsitem ? dsitem->GetDocument() : nullptr); + if (doc) { + nsCOMPtr uri; + nsIPrincipal* principal = doc->GetPrincipal(); + if (principal) { + principal->GetURI(getter_AddRefs(uri)); + if (uri) { + // + // remove any user:pass information + // + nsCOMPtr fixup(do_GetService(NS_URIFIXUP_CONTRACTID)); + if (fixup) { + nsCOMPtr tmpuri; + nsresult rv = fixup->CreateExposableURI(uri,getter_AddRefs(tmpuri)); + if (NS_SUCCEEDED(rv) && tmpuri) { + // (don't bother if there's no host) + nsAutoCString host; + nsAutoCString prepath; + tmpuri->GetHost(host); + tmpuri->GetPrePath(prepath); + if (!host.IsEmpty()) { + // + // We have a scheme/host, update the title + // + title.Insert(NS_ConvertUTF8toUTF16(prepath) + + mTitleSeparator, 0); + } + } + } + } + } + } + } + nsIDocument* document = docShellElement->OwnerDoc(); + ErrorResult rv; + document->SetTitle(title, rv); + return rv.StealNSResult(); + } + + return mXULWindow->SetTitle(title.get()); +} + +//***************************************************************************** +// nsContentTreeOwner: nsIWindowProvider +//***************************************************************************** +NS_IMETHODIMP +nsContentTreeOwner::ProvideWindow(mozIDOMWindowProxy* aParent, + uint32_t aChromeFlags, + bool aCalledFromJS, + bool aPositionSpecified, + bool aSizeSpecified, + nsIURI* aURI, + const nsAString& aName, + const nsACString& aFeatures, + bool aForceNoOpener, + bool* aWindowIsNew, + mozIDOMWindowProxy** aReturn) +{ + NS_ENSURE_ARG_POINTER(aParent); + + auto* parent = nsPIDOMWindowOuter::From(aParent); + + *aReturn = nullptr; + + if (!mXULWindow) { + // Nothing to do here + return NS_OK; + } + +#ifdef DEBUG + nsCOMPtr parentNav = do_GetInterface(aParent); + nsCOMPtr parentOwner = do_GetInterface(parentNav); + NS_ASSERTION(SameCOMIdentity(parentOwner, + static_cast(this)), + "Parent from wrong docshell tree?"); +#endif + + // If aParent is inside an