diff -r 000000000000 -r 6474c204b198 xpfe/appshell/src/nsContentTreeOwner.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xpfe/appshell/src/nsContentTreeOwner.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,1179 @@ +/* -*- 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 "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 +{ +public: + nsSiteWindow(nsContentTreeOwner *aAggregator); + virtual ~nsSiteWindow(); + + NS_DECL_ISUPPORTS + NS_DECL_NSIEMBEDDINGSITEWINDOW + +private: + 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))) { + 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::FindItemWithName(const char16_t* aName, + nsIDocShellTreeItem* aRequestor, nsIDocShellTreeItem* aOriginalRequestor, + nsIDocShellTreeItem** aFoundItem) +{ + NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); + + NS_ENSURE_ARG_POINTER(aFoundItem); + + *aFoundItem = nullptr; + + bool fIs_Content = false; + + /* Special Cases */ + if (!aName || !*aName) + return NS_OK; + + nsDependentString name(aName); + + if (name.LowerCaseEqualsLiteral("_blank")) + return NS_OK; + // _main is an IE target which should be case-insensitive but isn't + // see bug 217886 for details + if (name.LowerCaseEqualsLiteral("_content") || + name.EqualsLiteral("_main")) { + // If we're being called with an aRequestor and it's targetable, just + // return it -- _main and _content from inside targetable content shells + // should just be that content shell. Note that we don't have to worry + // about the case when it's not targetable because it's primary -- that + // will Just Work when we call GetPrimaryContentShell. + NS_ENSURE_STATE(mXULWindow); + if (aRequestor) { + // This better be the root item! +#ifdef DEBUG + nsCOMPtr debugRoot; + aRequestor->GetSameTypeRootTreeItem(getter_AddRefs(debugRoot)); + NS_ASSERTION(SameCOMIdentity(debugRoot, aRequestor), + "Bogus aRequestor"); +#endif + + int32_t count = mXULWindow->mTargetableShells.Count(); + for (int32_t i = 0; i < count; ++i) { + nsCOMPtr item = + do_QueryReferent(mXULWindow->mTargetableShells[i]); + if (SameCOMIdentity(item, aRequestor)) { + NS_ADDREF(*aFoundItem = aRequestor); + return NS_OK; + } + } + } + mXULWindow->GetPrimaryContentShell(aFoundItem); + if(*aFoundItem) + return NS_OK; + // Fall through and keep looking... + fIs_Content = true; + } + + nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); + NS_ENSURE_TRUE(windowMediator, NS_ERROR_FAILURE); + + nsCOMPtr windowEnumerator; + NS_ENSURE_SUCCESS(windowMediator->GetXULWindowEnumerator(nullptr, + getter_AddRefs(windowEnumerator)), NS_ERROR_FAILURE); + + bool more; + + windowEnumerator->HasMoreElements(&more); + while(more) { + nsCOMPtr nextWindow = nullptr; + windowEnumerator->GetNext(getter_AddRefs(nextWindow)); + nsCOMPtr xulWindow(do_QueryInterface(nextWindow)); + NS_ENSURE_TRUE(xulWindow, NS_ERROR_FAILURE); + + if (fIs_Content) { + xulWindow->GetPrimaryContentShell(aFoundItem); + } else { + // Get all the targetable windows from xulWindow and search them + nsRefPtr win; + xulWindow->QueryInterface(NS_GET_IID(nsXULWindow), getter_AddRefs(win)); + if (win) { + int32_t count = win->mTargetableShells.Count(); + int32_t i; + for (i = 0; i < count && !*aFoundItem; ++i) { + nsCOMPtr shellAsTreeItem = + do_QueryReferent(win->mTargetableShells[i]); + if (shellAsTreeItem) { + // Get the root tree item of same type, since roots are the only + // things that call into the treeowner to look for named items. + // XXXbz ideally we could guarantee that mTargetableShells only + // contains roots, but the current treeowner apis don't allow + // that... yet. + nsCOMPtr root; + shellAsTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(root)); + NS_ASSERTION(root, "Must have root tree item of same type"); + shellAsTreeItem.swap(root); + if (aRequestor != shellAsTreeItem) { + // Do this so we can pass in the tree owner as the + // requestor so the child knows not to call back up. + nsCOMPtr shellOwner; + shellAsTreeItem->GetTreeOwner(getter_AddRefs(shellOwner)); + nsCOMPtr shellOwnerSupports = + do_QueryInterface(shellOwner); + + shellAsTreeItem->FindItemWithName(aName, shellOwnerSupports, + aOriginalRequestor, + aFoundItem); + } + } + } + } + } + + if (*aFoundItem) + return NS_OK; + + windowEnumerator->HasMoreElements(&more); + } + return NS_OK; +} + +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::GetContentWindow(JSContext* aCx, + JS::MutableHandle aVal) +{ + NS_ENSURE_STATE(mXULWindow); + return NS_ERROR_NOT_IMPLEMENTED; +} + +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; +} + +//***************************************************************************** +// 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; +} + +//***************************************************************************** +// 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, false), 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::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, bool aRepaint) +{ + NS_ENSURE_STATE(mXULWindow); + return mXULWindow->SetPositionAndSize(aX, aY, aCX, aCY, aRepaint); +} + +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 domdoc(do_GetInterface(dsitem)); + nsCOMPtr doc(do_QueryInterface(domdoc)); + 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.ErrorCode(); + } + + return mXULWindow->SetTitle(title.get()); +} + +//***************************************************************************** +// nsContentTreeOwner: nsIWindowProvider +//***************************************************************************** +NS_IMETHODIMP +nsContentTreeOwner::ProvideWindow(nsIDOMWindow* aParent, + uint32_t aChromeFlags, + bool aCalledFromJS, + bool aPositionSpecified, + bool aSizeSpecified, + nsIURI* aURI, + const nsAString& aName, + const nsACString& aFeatures, + bool* aWindowIsNew, + nsIDOMWindow** aReturn) +{ + NS_ENSURE_ARG_POINTER(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