diff options
Diffstat (limited to 'xpfe/appshell/nsContentTreeOwner.cpp')
-rw-r--r-- | xpfe/appshell/nsContentTreeOwner.cpp | 1131 |
1 files changed, 1131 insertions, 0 deletions
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<nsIDocShell> 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<nsIDocShellTreeItem> shell; + mXULWindow->GetPrimaryContentShell(getter_AddRefs(shell)); + if (shell) { + nsCOMPtr<nsIInterfaceRequestor> 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<dom::Element> 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<dom::Element> 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<nsIXULBrowserWindow> 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<nsIXULBrowserWindow> 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<nsIXULBrowserWindow> xulBrowserWindow; + mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); + + if (xulBrowserWindow) + { + switch(aStatusType) + { + case STATUS_SCRIPT: + xulBrowserWindow->SetJSStatus(aStatusText); + break; + case STATUS_LINK: + { + nsCOMPtr<nsIDOMElement> 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<const nsString &>(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<dom::Element> 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<nsIDocShellTreeItem> dsitem; + GetPrimaryContentShell(getter_AddRefs(dsitem)); + nsCOMPtr<nsIScriptObjectPrincipal> doc = + do_QueryInterface(dsitem ? dsitem->GetDocument() : nullptr); + if (doc) { + nsCOMPtr<nsIURI> uri; + nsIPrincipal* principal = doc->GetPrincipal(); + if (principal) { + principal->GetURI(getter_AddRefs(uri)); + if (uri) { + // + // remove any user:pass information + // + nsCOMPtr<nsIURIFixup> fixup(do_GetService(NS_URIFIXUP_CONTRACTID)); + if (fixup) { + nsCOMPtr<nsIURI> 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<nsIWebNavigation> parentNav = do_GetInterface(aParent); + nsCOMPtr<nsIDocShellTreeOwner> parentOwner = do_GetInterface(parentNav); + NS_ASSERTION(SameCOMIdentity(parentOwner, + static_cast<nsIDocShellTreeOwner*>(this)), + "Parent from wrong docshell tree?"); +#endif + + // If aParent is inside an <iframe mozbrowser> and this isn't a request to + // open a modal-type window, we're going to create a new <iframe mozbrowser> + // and return its window here. + nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent); + if (docshell && docshell->GetIsInMozBrowserOrApp() && + !(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL | + nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | + nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) { + + BrowserElementParent::OpenWindowResult opened = + BrowserElementParent::OpenWindowInProcess(parent, aURI, aName, + aFeatures, aForceNoOpener, aReturn); + + // If OpenWindowInProcess handled the open (by opening it or blocking the + // popup), tell our caller not to proceed trying to create a new window + // through other means. + if (opened != BrowserElementParent::OPEN_WINDOW_IGNORED) { + *aWindowIsNew = opened == BrowserElementParent::OPEN_WINDOW_ADDED; + return *aWindowIsNew ? NS_OK : NS_ERROR_ABORT; + } + + // If we're in an app and the target is _blank, send the url to the OS + if (aName.LowerCaseEqualsLiteral("_blank")) { + nsCOMPtr<nsIExternalURLHandlerService> exUrlServ( + do_GetService(NS_EXTERNALURLHANDLERSERVICE_CONTRACTID)); + if (exUrlServ) { + + nsCOMPtr<nsIHandlerInfo> info; + bool found; + exUrlServ->GetURLHandlerInfoFromOS(aURI, &found, getter_AddRefs(info)); + + if (info && found) { + info->LaunchWithURI(aURI, nullptr); + return NS_ERROR_ABORT; + } + + } + } + } + + int32_t openLocation = + nsWindowWatcher::GetWindowOpenLocation(parent, aChromeFlags, aCalledFromJS, + aPositionSpecified, aSizeSpecified); + + if (openLocation != nsIBrowserDOMWindow::OPEN_NEWTAB && + openLocation != nsIBrowserDOMWindow::OPEN_CURRENTWINDOW) { + // Just open a window normally + return NS_OK; + } + + nsCOMPtr<mozIDOMWindowProxy> domWin; + mXULWindow->GetWindowDOMWindow(getter_AddRefs(domWin)); + nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(domWin); + if (!chromeWin) { + // Really odd... but whatever + NS_WARNING("nsXULWindow's DOMWindow is not a chrome window"); + return NS_OK; + } + + nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin; + chromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin)); + if (!browserDOMWin) { + return NS_OK; + } + + *aWindowIsNew = (openLocation != nsIBrowserDOMWindow::OPEN_CURRENTWINDOW); + + { + dom::AutoNoJSAPI nojsapi; + + uint32_t flags = nsIBrowserDOMWindow::OPEN_NEW; + if (aForceNoOpener) { + flags |= nsIBrowserDOMWindow::OPEN_NO_OPENER; + } + + // Get a new rendering area from the browserDOMWin. We don't want + // to be starting any loads here, so get it with a null URI. + // + // This method handles setting the opener for us, so we don't need to set it + // ourselves. + return browserDOMWin->OpenURI(nullptr, aParent, + openLocation, + flags, aReturn); + } +} + +//***************************************************************************** +// nsContentTreeOwner: Accessors +//***************************************************************************** + +#if defined(XP_MACOSX) +class nsContentTitleSettingEvent : public Runnable +{ +public: + nsContentTitleSettingEvent(dom::Element* dse, const nsAString& wtm) + : mElement(dse), + mTitleDefault(wtm) {} + + NS_IMETHOD Run() override + { + ErrorResult rv; + mElement->SetAttribute(NS_LITERAL_STRING("titledefault"), mTitleDefault, rv); + mElement->RemoveAttribute(NS_LITERAL_STRING("titlemodifier"), rv); + return NS_OK; + } + +private: + nsCOMPtr<dom::Element> mElement; + nsString mTitleDefault; +}; +#endif + +void nsContentTreeOwner::XULWindow(nsXULWindow* aXULWindow) +{ + mXULWindow = aXULWindow; + if (mXULWindow && mPrimary) { + // Get the window title modifiers + nsCOMPtr<dom::Element> docShellElement = mXULWindow->GetWindowDOMElement(); + + nsAutoString contentTitleSetting; + + if(docShellElement) + { + docShellElement->GetAttribute(NS_LITERAL_STRING("contenttitlesetting"), contentTitleSetting); + if(contentTitleSetting.EqualsLiteral("true")) + { + mContentTitleSetting = true; + docShellElement->GetAttribute(NS_LITERAL_STRING("titledefault"), mTitleDefault); + docShellElement->GetAttribute(NS_LITERAL_STRING("titlemodifier"), mWindowTitleModifier); + docShellElement->GetAttribute(NS_LITERAL_STRING("titlepreface"), mTitlePreface); + +#if defined(XP_MACOSX) + // On OS X, treat the titlemodifier like it's the titledefault, and don't ever append + // the separator + appname. + if (mTitleDefault.IsEmpty()) { + NS_DispatchToCurrentThread( + new nsContentTitleSettingEvent(docShellElement, + mWindowTitleModifier)); + mTitleDefault = mWindowTitleModifier; + mWindowTitleModifier.Truncate(); + } +#endif + docShellElement->GetAttribute(NS_LITERAL_STRING("titlemenuseparator"), mTitleSeparator); + } + } + else + { + NS_ERROR("This condition should never happen. If it does, " + "we just won't get a modifier, but it still shouldn't happen."); + } + } +} + +nsXULWindow* nsContentTreeOwner::XULWindow() +{ + return mXULWindow; +} + +//***************************************************************************** +//*** nsSiteWindow implementation +//***************************************************************************** + +nsSiteWindow::nsSiteWindow(nsContentTreeOwner *aAggregator) +{ + mAggregator = aAggregator; +} + +nsSiteWindow::~nsSiteWindow() +{ +} + +NS_IMPL_ADDREF_USING_AGGREGATOR(nsSiteWindow, mAggregator) +NS_IMPL_RELEASE_USING_AGGREGATOR(nsSiteWindow, mAggregator) + +NS_INTERFACE_MAP_BEGIN(nsSiteWindow) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow) +NS_INTERFACE_MAP_END_AGGREGATED(mAggregator) + +NS_IMETHODIMP +nsSiteWindow::SetDimensions(uint32_t aFlags, + int32_t aX, int32_t aY, int32_t aCX, int32_t aCY) +{ + // XXX we're ignoring aFlags + return mAggregator->SetPositionAndSize(aX, aY, aCX, aCY, + nsIBaseWindow::eRepaint); +} + +NS_IMETHODIMP +nsSiteWindow::GetDimensions(uint32_t aFlags, + int32_t *aX, int32_t *aY, int32_t *aCX, int32_t *aCY) +{ + // XXX we're ignoring aFlags + return mAggregator->GetPositionAndSize(aX, aY, aCX, aCY); +} + +NS_IMETHODIMP +nsSiteWindow::SetFocus(void) +{ +#if 0 + /* This implementation focuses the main document and could make sense. + However this method is actually being used from within + nsGlobalWindow::Focus (providing a hook for MDI embedding apps) + and it's better for our purposes to not pick a document and + focus it, but allow nsGlobalWindow to carry on unhindered. + */ + nsXULWindow *window = mAggregator->XULWindow(); + if (window) { + nsCOMPtr<nsIDocShell> docshell; + window->GetDocShell(getter_AddRefs(docshell)); + if (docShell) { + nsCOMPtr<nsPIDOMWindowOuter> domWindow(docShell->GetWindow()); + if (domWindow) + domWindow->Focus(); + } + } +#endif + return NS_OK; +} + +/* this implementation focuses another window. if there isn't another + window to focus, we do nothing. */ +NS_IMETHODIMP +nsSiteWindow::Blur(void) +{ + NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); + + nsCOMPtr<nsISimpleEnumerator> windowEnumerator; + nsCOMPtr<nsIXULWindow> xulWindow; + bool more, foundUs; + nsXULWindow *ourWindow = mAggregator->XULWindow(); + + { + nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(kWindowMediatorCID)); + if (windowMediator) + windowMediator->GetZOrderXULWindowEnumerator(0, true, + getter_AddRefs(windowEnumerator)); + } + + if (!windowEnumerator) + return NS_ERROR_FAILURE; + + // step through the top-level windows + foundUs = false; + windowEnumerator->HasMoreElements(&more); + while (more) { + + nsCOMPtr<nsISupports> nextWindow; + nsCOMPtr<nsIXULWindow> nextXULWindow; + + windowEnumerator->GetNext(getter_AddRefs(nextWindow)); + nextXULWindow = do_QueryInterface(nextWindow); + + // got it!(?) + if (foundUs) { + xulWindow = nextXULWindow; + break; + } + + // remember the very first one, in case we have to wrap + if (!xulWindow) + xulWindow = nextXULWindow; + + // look for us + if (nextXULWindow == ourWindow) + foundUs = true; + + windowEnumerator->HasMoreElements(&more); + } + + // change focus to the window we just found + if (xulWindow) { + nsCOMPtr<nsIDocShell> docshell; + xulWindow->GetDocShell(getter_AddRefs(docshell)); + if (!docshell) { + return NS_OK; + } + + nsCOMPtr<nsPIDOMWindowOuter> domWindow = docshell->GetWindow(); + if (domWindow) + domWindow->Focus(); + } + return NS_OK; +} + +NS_IMETHODIMP +nsSiteWindow::GetVisibility(bool *aVisibility) +{ + return mAggregator->GetVisibility(aVisibility); +} + +NS_IMETHODIMP +nsSiteWindow::SetVisibility(bool aVisibility) +{ + return mAggregator->SetVisibility(aVisibility); +} + +NS_IMETHODIMP +nsSiteWindow::GetTitle(char16_t * *aTitle) +{ + return mAggregator->GetTitle(aTitle); +} + +NS_IMETHODIMP +nsSiteWindow::SetTitle(const char16_t * aTitle) +{ + return mAggregator->SetTitle(aTitle); +} + +NS_IMETHODIMP +nsSiteWindow::GetSiteWindow(void **aSiteWindow) +{ + return mAggregator->GetParentNativeWindow(aSiteWindow); +} + |