diff options
Diffstat (limited to 'embedding/browser/nsWebBrowser.cpp')
-rw-r--r-- | embedding/browser/nsWebBrowser.cpp | 1952 |
1 files changed, 1952 insertions, 0 deletions
diff --git a/embedding/browser/nsWebBrowser.cpp b/embedding/browser/nsWebBrowser.cpp new file mode 100644 index 000000000..655aa1e43 --- /dev/null +++ b/embedding/browser/nsWebBrowser.cpp @@ -0,0 +1,1952 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "nsWebBrowser.h" + +// Helper Classes +#include "nsGfxCIID.h" +#include "nsWidgetsCID.h" + +#include "gfxUtils.h" +#include "mozilla/gfx/2D.h" + +// Interfaces Needed +#include "nsReadableUtils.h" +#include "nsIComponentManager.h" +#include "nsIDOMDocument.h" +#include "nsIDOMWindow.h" +#include "nsIDOMElement.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIWebBrowserChrome.h" +#include "nsPIDOMWindow.h" +#include "nsIWebProgress.h" +#include "nsIWebProgressListener.h" +#include "nsIWebBrowserFocus.h" +#include "nsIWebBrowserStream.h" +#include "nsIPresShell.h" +#include "nsIURIContentListener.h" +#include "nsISHistoryListener.h" +#include "nsIURI.h" +#include "nsIWebBrowserPersist.h" +#include "nsCWebBrowserPersist.h" +#include "nsIServiceManager.h" +#include "nsFocusManager.h" +#include "Layers.h" +#include "gfxContext.h" +#include "nsILoadContext.h" +#include "nsDocShell.h" + +// for painting the background window +#include "mozilla/LookAndFeel.h" + +// Printing Includes +#ifdef NS_PRINTING +#include "nsIWebBrowserPrint.h" +#include "nsIContentViewer.h" +#endif + +// PSM2 includes +#include "nsISecureBrowserUI.h" +#include "nsXULAppAPI.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::layers; + +static NS_DEFINE_CID(kChildCID, NS_CHILD_CID); + +nsWebBrowser::nsWebBrowser() + : mInitInfo(new nsWebBrowserInitInfo()) + , mContentType(typeContentWrapper) + , mActivating(false) + , mShouldEnableHistory(true) + , mIsActive(true) + , mParentNativeWindow(nullptr) + , mProgressListener(nullptr) + , mWidgetListenerDelegate(this) + , mBackgroundColor(0) + , mPersistCurrentState(nsIWebBrowserPersist::PERSIST_STATE_READY) + , mPersistResult(NS_OK) + , mPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_NONE) + , mParentWidget(nullptr) +{ + mWWatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID); + NS_ASSERTION(mWWatch, "failed to get WindowWatcher"); +} + +nsWebBrowser::~nsWebBrowser() +{ + InternalDestroy(); +} + +NS_IMETHODIMP +nsWebBrowser::InternalDestroy() +{ + if (mInternalWidget) { + mInternalWidget->SetWidgetListener(nullptr); + mInternalWidget->Destroy(); + mInternalWidget = nullptr; // Force release here. + } + + SetDocShell(nullptr); + + if (mDocShellTreeOwner) { + mDocShellTreeOwner->WebBrowser(nullptr); + mDocShellTreeOwner = nullptr; + } + + mInitInfo = nullptr; + + mListenerArray = nullptr; + + return NS_OK; +} + +NS_IMPL_ADDREF(nsWebBrowser) +NS_IMPL_RELEASE(nsWebBrowser) + +NS_INTERFACE_MAP_BEGIN(nsWebBrowser) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowser) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowser) + NS_INTERFACE_MAP_ENTRY(nsIWebNavigation) + NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) + NS_INTERFACE_MAP_ENTRY(nsIScrollable) + NS_INTERFACE_MAP_ENTRY(nsITextScroll) + NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserSetup) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersist) + NS_INTERFACE_MAP_ENTRY(nsICancelable) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserFocus) + NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserStream) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) +NS_INTERFACE_MAP_END + +///***************************************************************************** +// nsWebBrowser::nsIInterfaceRequestor +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetInterface(const nsIID& aIID, void** aSink) +{ + NS_ENSURE_ARG_POINTER(aSink); + + if (NS_SUCCEEDED(QueryInterface(aIID, aSink))) { + return NS_OK; + } + + if (mDocShell) { +#ifdef NS_PRINTING + if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) { + nsCOMPtr<nsIContentViewer> viewer; + mDocShell->GetContentViewer(getter_AddRefs(viewer)); + if (!viewer) { + return NS_NOINTERFACE; + } + + nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint(do_QueryInterface(viewer)); + nsIWebBrowserPrint* print = (nsIWebBrowserPrint*)webBrowserPrint.get(); + NS_ASSERTION(print, "This MUST support this interface!"); + NS_ADDREF(print); + *aSink = print; + return NS_OK; + } +#endif + return mDocShellAsReq->GetInterface(aIID, aSink); + } + + return NS_NOINTERFACE; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebBrowser +//***************************************************************************** + +// listeners that currently support registration through AddWebBrowserListener: +// - nsIWebProgressListener +NS_IMETHODIMP +nsWebBrowser::AddWebBrowserListener(nsIWeakReference* aListener, + const nsIID& aIID) +{ + NS_ENSURE_ARG_POINTER(aListener); + + nsresult rv = NS_OK; + if (!mWebProgress) { + // The window hasn't been created yet, so queue up the listener. They'll be + // registered when the window gets created. + if (!mListenerArray) { + mListenerArray = new nsTArray<nsWebBrowserListenerState>(); + } + + nsWebBrowserListenerState* state = mListenerArray->AppendElement(); + state->mWeakPtr = aListener; + state->mID = aIID; + } else { + nsCOMPtr<nsISupports> supports(do_QueryReferent(aListener)); + if (!supports) { + return NS_ERROR_INVALID_ARG; + } + rv = BindListener(supports, aIID); + } + + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::BindListener(nsISupports* aListener, const nsIID& aIID) +{ + NS_ENSURE_ARG_POINTER(aListener); + NS_ASSERTION(mWebProgress, + "this should only be called after we've retrieved a progress iface"); + nsresult rv = NS_OK; + + // register this listener for the specified interface id + if (aIID.Equals(NS_GET_IID(nsIWebProgressListener))) { + nsCOMPtr<nsIWebProgressListener> listener = do_QueryInterface(aListener, &rv); + if (NS_FAILED(rv)) { + return rv; + } + NS_ENSURE_STATE(mWebProgress); + rv = mWebProgress->AddProgressListener(listener, nsIWebProgress::NOTIFY_ALL); + } else if (aIID.Equals(NS_GET_IID(nsISHistoryListener))) { + nsCOMPtr<nsISHistory> shistory(do_GetInterface(mDocShell, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr<nsISHistoryListener> listener(do_QueryInterface(aListener, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + rv = shistory->AddSHistoryListener(listener); + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::RemoveWebBrowserListener(nsIWeakReference* aListener, + const nsIID& aIID) +{ + NS_ENSURE_ARG_POINTER(aListener); + + nsresult rv = NS_OK; + if (!mWebProgress) { + // if there's no-one to register the listener w/, and we don't have a queue + // going, the the called is calling Remove before an Add which doesn't make + // sense. + if (!mListenerArray) { + return NS_ERROR_FAILURE; + } + + // iterate the array and remove the queued listener + int32_t count = mListenerArray->Length(); + while (count > 0) { + if (mListenerArray->ElementAt(count-1).Equals(aListener, aIID)) { + mListenerArray->RemoveElementAt(count-1); + break; + } + count--; + } + + // if we've emptied the array, get rid of it. + if (0 >= mListenerArray->Length()) { + mListenerArray = nullptr; + } + + } else { + nsCOMPtr<nsISupports> supports(do_QueryReferent(aListener)); + if (!supports) { + return NS_ERROR_INVALID_ARG; + } + rv = UnBindListener(supports, aIID); + } + + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::UnBindListener(nsISupports* aListener, const nsIID& aIID) +{ + NS_ENSURE_ARG_POINTER(aListener); + NS_ASSERTION(mWebProgress, + "this should only be called after we've retrieved a progress iface"); + nsresult rv = NS_OK; + + // remove the listener for the specified interface id + if (aIID.Equals(NS_GET_IID(nsIWebProgressListener))) { + nsCOMPtr<nsIWebProgressListener> listener = do_QueryInterface(aListener, &rv); + if (NS_FAILED(rv)) { + return rv; + } + NS_ENSURE_STATE(mWebProgress); + rv = mWebProgress->RemoveProgressListener(listener); + } else if (aIID.Equals(NS_GET_IID(nsISHistoryListener))) { + nsCOMPtr<nsISHistory> shistory(do_GetInterface(mDocShell, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr<nsISHistoryListener> listener(do_QueryInterface(aListener, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + rv = shistory->RemoveSHistoryListener(listener); + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::EnableGlobalHistory(bool aEnable) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShell->SetUseGlobalHistory(aEnable); +} + +NS_IMETHODIMP +nsWebBrowser::GetContainerWindow(nsIWebBrowserChrome** aTopWindow) +{ + NS_ENSURE_ARG_POINTER(aTopWindow); + + nsCOMPtr<nsIWebBrowserChrome> top; + if (mDocShellTreeOwner) { + top = mDocShellTreeOwner->GetWebBrowserChrome(); + } + + top.forget(aTopWindow); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetContainerWindow(nsIWebBrowserChrome* aTopWindow) +{ + NS_ENSURE_SUCCESS(EnsureDocShellTreeOwner(), NS_ERROR_FAILURE); + return mDocShellTreeOwner->SetWebBrowserChrome(aTopWindow); +} + +NS_IMETHODIMP +nsWebBrowser::GetParentURIContentListener( + nsIURIContentListener** aParentContentListener) +{ + NS_ENSURE_ARG_POINTER(aParentContentListener); + *aParentContentListener = nullptr; + + // get the interface from the docshell + nsCOMPtr<nsIURIContentListener> listener(do_GetInterface(mDocShell)); + + if (listener) { + return listener->GetParentContentListener(aParentContentListener); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetParentURIContentListener( + nsIURIContentListener* aParentContentListener) +{ + // get the interface from the docshell + nsCOMPtr<nsIURIContentListener> listener(do_GetInterface(mDocShell)); + + if (listener) { + return listener->SetParentContentListener(aParentContentListener); + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWebBrowser::GetContentDOMWindow(mozIDOMWindowProxy** aResult) +{ + if (!mDocShell) { + return NS_ERROR_UNEXPECTED; + } + + nsCOMPtr<nsPIDOMWindowOuter> retval = mDocShell->GetWindow(); + retval.forget(aResult); + return *aResult ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWebBrowser::GetIsActive(bool* aResult) +{ + *aResult = mIsActive; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetIsActive(bool aIsActive) +{ + // Set our copy of the value + mIsActive = aIsActive; + + // If we have a docshell, pass on the request + if (mDocShell) { + return mDocShell->SetIsActive(aIsActive); + } + return NS_OK; +} + +void +nsWebBrowser::SetOriginAttributes(const DocShellOriginAttributes& aAttrs) +{ + mOriginAttributes = aAttrs; +} + +//***************************************************************************** +// nsWebBrowser::nsIDocShellTreeItem +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetName(nsAString& aName) +{ + if (mDocShell) { + mDocShell->GetName(aName); + } else { + aName = mInitInfo->name; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetName(const nsAString& aName) +{ + if (mDocShell) { + return mDocShell->SetName(aName); + } else { + mInitInfo->name = aName; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::NameEquals(const nsAString& aName, bool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + if (mDocShell) { + return mDocShell->NameEquals(aName, aResult); + } else { + *aResult = mInitInfo->name.Equals(aName); + } + + return NS_OK; +} + +/* virtual */ int32_t +nsWebBrowser::ItemType() +{ + return mContentType; +} + +NS_IMETHODIMP +nsWebBrowser::GetItemType(int32_t* aItemType) +{ + NS_ENSURE_ARG_POINTER(aItemType); + + *aItemType = ItemType(); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetItemType(int32_t aItemType) +{ + NS_ENSURE_TRUE( + aItemType == typeContentWrapper || aItemType == typeChromeWrapper, + NS_ERROR_FAILURE); + mContentType = aItemType; + if (mDocShell) { + mDocShell->SetItemType(mContentType == typeChromeWrapper ? + static_cast<int32_t>(typeChrome) : + static_cast<int32_t>(typeContent)); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetParent(nsIDocShellTreeItem** aParent) +{ + *aParent = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetSameTypeParent(nsIDocShellTreeItem** aParent) +{ + *aParent = nullptr; + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) +{ + NS_ENSURE_ARG_POINTER(aRootTreeItem); + *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this); + + nsCOMPtr<nsIDocShellTreeItem> parent; + NS_ENSURE_SUCCESS(GetParent(getter_AddRefs(parent)), NS_ERROR_FAILURE); + while (parent) { + *aRootTreeItem = parent; + NS_ENSURE_SUCCESS((*aRootTreeItem)->GetParent(getter_AddRefs(parent)), + NS_ERROR_FAILURE); + } + NS_ADDREF(*aRootTreeItem); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetSameTypeRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) +{ + NS_ENSURE_ARG_POINTER(aRootTreeItem); + *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this); + + nsCOMPtr<nsIDocShellTreeItem> parent; + NS_ENSURE_SUCCESS(GetSameTypeParent(getter_AddRefs(parent)), + NS_ERROR_FAILURE); + while (parent) { + *aRootTreeItem = parent; + NS_ENSURE_SUCCESS((*aRootTreeItem)->GetSameTypeParent(getter_AddRefs(parent)), + NS_ERROR_FAILURE); + } + NS_ADDREF(*aRootTreeItem); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::FindItemWithName(const nsAString& aName, + nsISupports* aRequestor, + nsIDocShellTreeItem* aOriginalRequestor, + nsIDocShellTreeItem** aResult) +{ + NS_ENSURE_STATE(mDocShell); + NS_ASSERTION(mDocShellTreeOwner, + "This should always be set when in this situation"); + + return mDocShell->FindItemWithName( + aName, static_cast<nsIDocShellTreeOwner*>(mDocShellTreeOwner), + aOriginalRequestor, aResult); +} + +nsIDocument* +nsWebBrowser::GetDocument() +{ + return mDocShell ? mDocShell->GetDocument() : nullptr; +} + +nsPIDOMWindowOuter* +nsWebBrowser::GetWindow() +{ + return mDocShell ? mDocShell->GetWindow() : nullptr; +} + +NS_IMETHODIMP +nsWebBrowser::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) +{ + NS_ENSURE_ARG_POINTER(aTreeOwner); + *aTreeOwner = nullptr; + if (mDocShellTreeOwner) { + if (mDocShellTreeOwner->mTreeOwner) { + *aTreeOwner = mDocShellTreeOwner->mTreeOwner; + } else { + *aTreeOwner = mDocShellTreeOwner; + } + } + NS_IF_ADDREF(*aTreeOwner); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) +{ + NS_ENSURE_SUCCESS(EnsureDocShellTreeOwner(), NS_ERROR_FAILURE); + return mDocShellTreeOwner->SetTreeOwner(aTreeOwner); +} + +//***************************************************************************** +// nsWebBrowser::nsIDocShellTreeItem +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetChildCount(int32_t* aChildCount) +{ + NS_ENSURE_ARG_POINTER(aChildCount); + *aChildCount = 0; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::AddChild(nsIDocShellTreeItem* aChild) +{ + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsWebBrowser::RemoveChild(nsIDocShellTreeItem* aChild) +{ + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsWebBrowser::GetChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) +{ + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsWebBrowser::FindChildWithName(const nsAString& aName, + bool aRecurse, + bool aSameType, + nsIDocShellTreeItem* aRequestor, + nsIDocShellTreeItem* aOriginalRequestor, + nsIDocShellTreeItem** aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + + *aResult = nullptr; + return NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebNavigation +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetCanGoBack(bool* aCanGoBack) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetCanGoBack(aCanGoBack); +} + +NS_IMETHODIMP +nsWebBrowser::GetCanGoForward(bool* aCanGoForward) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetCanGoForward(aCanGoForward); +} + +NS_IMETHODIMP +nsWebBrowser::GoBack() +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GoBack(); +} + +NS_IMETHODIMP +nsWebBrowser::GoForward() +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GoForward(); +} + +NS_IMETHODIMP +nsWebBrowser::LoadURIWithOptions(const char16_t* aURI, uint32_t aLoadFlags, + nsIURI* aReferringURI, + uint32_t aReferrerPolicy, + nsIInputStream* aPostDataStream, + nsIInputStream* aExtraHeaderStream, + nsIURI* aBaseURI) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->LoadURIWithOptions( + aURI, aLoadFlags, aReferringURI, aReferrerPolicy, aPostDataStream, + aExtraHeaderStream, aBaseURI); +} + +NS_IMETHODIMP +nsWebBrowser::SetOriginAttributesBeforeLoading(JS::Handle<JS::Value> aOriginAttributes) +{ + return mDocShellAsNav->SetOriginAttributesBeforeLoading(aOriginAttributes); +} + +NS_IMETHODIMP +nsWebBrowser::LoadURI(const char16_t* aURI, uint32_t aLoadFlags, + nsIURI* aReferringURI, + nsIInputStream* aPostDataStream, + nsIInputStream* aExtraHeaderStream) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->LoadURI( + aURI, aLoadFlags, aReferringURI, aPostDataStream, aExtraHeaderStream); +} + +NS_IMETHODIMP +nsWebBrowser::Reload(uint32_t aReloadFlags) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->Reload(aReloadFlags); +} + +NS_IMETHODIMP +nsWebBrowser::GotoIndex(int32_t aIndex) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GotoIndex(aIndex); +} + +NS_IMETHODIMP +nsWebBrowser::Stop(uint32_t aStopFlags) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->Stop(aStopFlags); +} + +NS_IMETHODIMP +nsWebBrowser::GetCurrentURI(nsIURI** aURI) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetCurrentURI(aURI); +} + +NS_IMETHODIMP +nsWebBrowser::GetReferringURI(nsIURI** aURI) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetReferringURI(aURI); +} + +NS_IMETHODIMP +nsWebBrowser::SetSessionHistory(nsISHistory* aSessionHistory) +{ + if (mDocShell) { + return mDocShellAsNav->SetSessionHistory(aSessionHistory); + } else { + mInitInfo->sessionHistory = aSessionHistory; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetSessionHistory(nsISHistory** aSessionHistory) +{ + NS_ENSURE_ARG_POINTER(aSessionHistory); + if (mDocShell) { + return mDocShellAsNav->GetSessionHistory(aSessionHistory); + } else { + *aSessionHistory = mInitInfo->sessionHistory; + } + + NS_IF_ADDREF(*aSessionHistory); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetDocument(nsIDOMDocument** aDocument) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetDocument(aDocument); +} + +//***************************************************************************** +// nsWebBrowser::nsIWebBrowserSetup +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::SetProperty(uint32_t aId, uint32_t aValue) +{ + nsresult rv = NS_OK; + + switch (aId) { + case nsIWebBrowserSetup::SETUP_ALLOW_PLUGINS: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowPlugins(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_JAVASCRIPT: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowJavascript(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_META_REDIRECTS: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowMetaRedirects(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_SUBFRAMES: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowSubframes(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_IMAGES: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowImages(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowDNSPrefetch(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_USE_GLOBAL_HISTORY: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + rv = EnableGlobalHistory(!!aValue); + mShouldEnableHistory = aValue; + break; + } + case nsIWebBrowserSetup::SETUP_FOCUS_DOC_BEFORE_CONTENT: { + // obsolete + break; + } + case nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER: { + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + SetItemType(aValue ? static_cast<int32_t>(typeChromeWrapper) : + static_cast<int32_t>(typeContentWrapper)); + break; + } + default: + rv = NS_ERROR_INVALID_ARG; + } + return rv; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebProgressListener +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::OnStateChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + uint32_t aStateFlags, + nsresult aStatus) +{ + if (mPersist) { + mPersist->GetCurrentState(&mPersistCurrentState); + } + if (aStateFlags & STATE_IS_NETWORK && aStateFlags & STATE_STOP) { + mPersist = nullptr; + } + if (mProgressListener) { + return mProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, + aStatus); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::OnProgressChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + int32_t aCurSelfProgress, + int32_t aMaxSelfProgress, + int32_t aCurTotalProgress, + int32_t aMaxTotalProgress) +{ + if (mPersist) { + mPersist->GetCurrentState(&mPersistCurrentState); + } + if (mProgressListener) { + return mProgressListener->OnProgressChange( + aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, + aCurTotalProgress, aMaxTotalProgress); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::OnLocationChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsIURI* aLocation, + uint32_t aFlags) +{ + if (mProgressListener) { + return mProgressListener->OnLocationChange(aWebProgress, aRequest, aLocation, + aFlags); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::OnStatusChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsresult aStatus, + const char16_t* aMessage) +{ + if (mProgressListener) { + return mProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, + aMessage); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::OnSecurityChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + uint32_t aState) +{ + if (mProgressListener) { + return mProgressListener->OnSecurityChange(aWebProgress, aRequest, aState); + } + return NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebBrowserPersist +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetPersistFlags(uint32_t* aPersistFlags) +{ + NS_ENSURE_ARG_POINTER(aPersistFlags); + nsresult rv = NS_OK; + if (mPersist) { + rv = mPersist->GetPersistFlags(&mPersistFlags); + } + *aPersistFlags = mPersistFlags; + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::SetPersistFlags(uint32_t aPersistFlags) +{ + nsresult rv = NS_OK; + mPersistFlags = aPersistFlags; + if (mPersist) { + rv = mPersist->SetPersistFlags(mPersistFlags); + mPersist->GetPersistFlags(&mPersistFlags); + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::GetCurrentState(uint32_t* aCurrentState) +{ + NS_ENSURE_ARG_POINTER(aCurrentState); + if (mPersist) { + mPersist->GetCurrentState(&mPersistCurrentState); + } + *aCurrentState = mPersistCurrentState; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetResult(nsresult* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + if (mPersist) { + mPersist->GetResult(&mPersistResult); + } + *aResult = mPersistResult; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetProgressListener(nsIWebProgressListener** aProgressListener) +{ + NS_ENSURE_ARG_POINTER(aProgressListener); + *aProgressListener = mProgressListener; + NS_IF_ADDREF(*aProgressListener); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetProgressListener(nsIWebProgressListener* aProgressListener) +{ + mProgressListener = aProgressListener; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SaveURI(nsIURI* aURI, + nsISupports* aCacheKey, + nsIURI* aReferrer, + uint32_t aReferrerPolicy, + nsIInputStream* aPostData, + const char* aExtraHeaders, + nsISupports* aFile, + nsILoadContext* aPrivacyContext) +{ + return SavePrivacyAwareURI( + aURI, aCacheKey, aReferrer, aReferrerPolicy, aPostData, aExtraHeaders, + aFile, aPrivacyContext && aPrivacyContext->UsePrivateBrowsing()); +} + +NS_IMETHODIMP +nsWebBrowser::SavePrivacyAwareURI(nsIURI* aURI, + nsISupports* aCacheKey, + nsIURI* aReferrer, + uint32_t aReferrerPolicy, + nsIInputStream* aPostData, + const char* aExtraHeaders, + nsISupports* aFile, + bool aIsPrivate) +{ + if (mPersist) { + uint32_t currentState; + mPersist->GetCurrentState(¤tState); + if (currentState == PERSIST_STATE_FINISHED) { + mPersist = nullptr; + } else { + // You can't save again until the last save has completed + return NS_ERROR_FAILURE; + } + } + + nsCOMPtr<nsIURI> uri; + if (aURI) { + uri = aURI; + } else { + nsresult rv = GetCurrentURI(getter_AddRefs(uri)); + if (NS_FAILED(rv)) { + return NS_ERROR_FAILURE; + } + } + + // Create a throwaway persistence object to do the work + nsresult rv; + mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + mPersist->SetProgressListener(this); + mPersist->SetPersistFlags(mPersistFlags); + mPersist->GetCurrentState(&mPersistCurrentState); + + rv = mPersist->SavePrivacyAwareURI(uri, aCacheKey, aReferrer, aReferrerPolicy, + aPostData, aExtraHeaders, aFile, aIsPrivate); + if (NS_FAILED(rv)) { + mPersist = nullptr; + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::SaveChannel(nsIChannel* aChannel, nsISupports* aFile) +{ + if (mPersist) { + uint32_t currentState; + mPersist->GetCurrentState(¤tState); + if (currentState == PERSIST_STATE_FINISHED) { + mPersist = nullptr; + } else { + // You can't save again until the last save has completed + return NS_ERROR_FAILURE; + } + } + + // Create a throwaway persistence object to do the work + nsresult rv; + mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + mPersist->SetProgressListener(this); + mPersist->SetPersistFlags(mPersistFlags); + mPersist->GetCurrentState(&mPersistCurrentState); + rv = mPersist->SaveChannel(aChannel, aFile); + if (NS_FAILED(rv)) { + mPersist = nullptr; + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::SaveDocument(nsISupports* aDocumentish, + nsISupports* aFile, + nsISupports* aDataPath, + const char* aOutputContentType, + uint32_t aEncodingFlags, + uint32_t aWrapColumn) +{ + if (mPersist) { + uint32_t currentState; + mPersist->GetCurrentState(¤tState); + if (currentState == PERSIST_STATE_FINISHED) { + mPersist = nullptr; + } else { + // You can't save again until the last save has completed + return NS_ERROR_FAILURE; + } + } + + // Use the specified DOM document, or if none is specified, the one + // attached to the web browser. + + nsCOMPtr<nsISupports> doc; + if (aDocumentish) { + doc = aDocumentish; + } else { + nsCOMPtr<nsIDOMDocument> domDoc; + GetDocument(getter_AddRefs(domDoc)); + doc = domDoc.forget(); + } + if (!doc) { + return NS_ERROR_FAILURE; + } + + // Create a throwaway persistence object to do the work + nsresult rv; + mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + mPersist->SetProgressListener(this); + mPersist->SetPersistFlags(mPersistFlags); + mPersist->GetCurrentState(&mPersistCurrentState); + rv = mPersist->SaveDocument(doc, aFile, aDataPath, aOutputContentType, + aEncodingFlags, aWrapColumn); + if (NS_FAILED(rv)) { + mPersist = nullptr; + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::CancelSave() +{ + if (mPersist) { + return mPersist->CancelSave(); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Cancel(nsresult aReason) +{ + if (mPersist) { + return mPersist->Cancel(aReason); + } + return NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIBaseWindow +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::InitWindow(nativeWindow aParentNativeWindow, + nsIWidget* aParentWidget, + int32_t aX, int32_t aY, + int32_t aCX, int32_t aCY) +{ + NS_ENSURE_ARG(aParentNativeWindow || aParentWidget); + NS_ENSURE_STATE(!mDocShell || mInitInfo); + + if (aParentWidget) { + NS_ENSURE_SUCCESS(SetParentWidget(aParentWidget), NS_ERROR_FAILURE); + } else + NS_ENSURE_SUCCESS(SetParentNativeWindow(aParentNativeWindow), + NS_ERROR_FAILURE); + + NS_ENSURE_SUCCESS(SetPositionAndSize(aX, aY, aCX, aCY, 0), + NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Create() +{ + NS_ENSURE_STATE(!mDocShell && (mParentNativeWindow || mParentWidget)); + + nsresult rv = EnsureDocShellTreeOwner(); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIWidget> docShellParentWidget(mParentWidget); + if (!mParentWidget) { + // Create the widget + mInternalWidget = do_CreateInstance(kChildCID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + docShellParentWidget = mInternalWidget; + nsWidgetInitData widgetInit; + + widgetInit.clipChildren = true; + + widgetInit.mWindowType = eWindowType_child; + LayoutDeviceIntRect bounds(mInitInfo->x, mInitInfo->y, + mInitInfo->cx, mInitInfo->cy); + + mInternalWidget->SetWidgetListener(&mWidgetListenerDelegate); + rv = mInternalWidget->Create(nullptr, mParentNativeWindow, bounds, + &widgetInit); + NS_ENSURE_SUCCESS(rv, rv); + } + + nsCOMPtr<nsIDocShell> docShell( + do_CreateInstance("@mozilla.org/docshell;1", &rv)); + NS_ENSURE_SUCCESS(rv, rv); + nsDocShell::Cast(docShell)->SetOriginAttributes(mOriginAttributes); + rv = SetDocShell(docShell); + NS_ENSURE_SUCCESS(rv, rv); + + // get the system default window background colour + LookAndFeel::GetColor(LookAndFeel::eColorID_WindowBackground, + &mBackgroundColor); + + // the docshell has been set so we now have our listener registrars. + if (mListenerArray) { + // we had queued up some listeners, let's register them now. + uint32_t count = mListenerArray->Length(); + uint32_t i = 0; + NS_ASSERTION(count > 0, "array construction problem"); + while (i < count) { + nsWebBrowserListenerState& state = mListenerArray->ElementAt(i); + nsCOMPtr<nsISupports> listener = do_QueryReferent(state.mWeakPtr); + NS_ASSERTION(listener, "bad listener"); + (void)BindListener(listener, state.mID); + i++; + } + mListenerArray = nullptr; + } + + // HACK ALERT - this registration registers the nsDocShellTreeOwner as a + // nsIWebBrowserListener so it can setup its MouseListener in one of the + // progress callbacks. If we can register the MouseListener another way, this + // registration can go away, and nsDocShellTreeOwner can stop implementing + // nsIWebProgressListener. + nsCOMPtr<nsISupports> supports = nullptr; + (void)mDocShellTreeOwner->QueryInterface( + NS_GET_IID(nsIWebProgressListener), + static_cast<void**>(getter_AddRefs(supports))); + (void)BindListener(supports, NS_GET_IID(nsIWebProgressListener)); + + NS_ENSURE_SUCCESS(mDocShellAsWin->InitWindow(nullptr, docShellParentWidget, + mInitInfo->x, mInitInfo->y, + mInitInfo->cx, mInitInfo->cy), + NS_ERROR_FAILURE); + + mDocShell->SetName(mInitInfo->name); + if (mContentType == typeChromeWrapper) { + mDocShell->SetItemType(nsIDocShellTreeItem::typeChrome); + } else { + mDocShell->SetItemType(nsIDocShellTreeItem::typeContent); + } + mDocShell->SetTreeOwner(mDocShellTreeOwner); + + // If the webbrowser is a content docshell item then we won't hear any + // events from subframes. To solve that we install our own chrome event + // handler that always gets called (even for subframes) for any bubbling + // event. + + if (!mInitInfo->sessionHistory) { + mInitInfo->sessionHistory = do_CreateInstance(NS_SHISTORY_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + } + mDocShellAsNav->SetSessionHistory(mInitInfo->sessionHistory); + + if (XRE_IsParentProcess()) { + // Hook up global history. Do not fail if we can't - just warn. + rv = EnableGlobalHistory(mShouldEnableHistory); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "EnableGlobalHistory() failed"); + } + + NS_ENSURE_SUCCESS(mDocShellAsWin->Create(), NS_ERROR_FAILURE); + + // Hook into the OnSecurityChange() notification for lock/unlock icon + // updates + nsCOMPtr<mozIDOMWindowProxy> domWindow; + rv = GetContentDOMWindow(getter_AddRefs(domWindow)); + if (NS_SUCCEEDED(rv)) { + // this works because the implementation of nsISecureBrowserUI + // (nsSecureBrowserUIImpl) gets a docShell from the domWindow, + // and calls docShell->SetSecurityUI(this); + nsCOMPtr<nsISecureBrowserUI> securityUI = + do_CreateInstance(NS_SECURE_BROWSER_UI_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) { + securityUI->Init(domWindow); + } + } + + mDocShellTreeOwner->AddToWatcher(); // evil twin of Remove in SetDocShell(0) + mDocShellTreeOwner->AddChromeListeners(); + + mInitInfo = nullptr; + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Destroy() +{ + InternalDestroy(); + + if (!mInitInfo) { + mInitInfo = new nsWebBrowserInitInfo(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetUnscaledDevicePixelsPerCSSPixel(double* aScale) +{ + *aScale = mParentWidget ? mParentWidget->GetDefaultScale().scale : 1.0; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetDevicePixelsPerDesktopPixel(double* aScale) +{ + *aScale = mParentWidget ? mParentWidget->GetDesktopToDeviceScale().scale + : 1.0; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetPositionDesktopPix(int32_t aX, int32_t aY) +{ + // XXX jfkthame + // It's not clear to me whether this will be fully correct across + // potential multi-screen, mixed-DPI configurations for all platforms; + // we might need to add code paths that make it possible to pass the + // desktop-pix parameters all the way through to the native widget, + // to avoid the risk of device-pixel coords mapping to the wrong + // display on OS X with mixed retina/non-retina screens. + double scale = 1.0; + GetDevicePixelsPerDesktopPixel(&scale); + return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale)); +} + +NS_IMETHODIMP +nsWebBrowser::SetPosition(int32_t aX, int32_t aY) +{ + int32_t cx = 0; + int32_t cy = 0; + + GetSize(&cx, &cy); + + return SetPositionAndSize(aX, aY, cx, cy, 0); +} + +NS_IMETHODIMP +nsWebBrowser::GetPosition(int32_t* aX, int32_t* aY) +{ + return GetPositionAndSize(aX, aY, nullptr, nullptr); +} + +NS_IMETHODIMP +nsWebBrowser::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) +{ + int32_t x = 0; + int32_t y = 0; + + GetPosition(&x, &y); + + return SetPositionAndSize(x, y, aCX, aCY, + aRepaint ? nsIBaseWindow::eRepaint : 0); +} + +NS_IMETHODIMP +nsWebBrowser::GetSize(int32_t* aCX, int32_t* aCY) +{ + return GetPositionAndSize(nullptr, nullptr, aCX, aCY); +} + +NS_IMETHODIMP +nsWebBrowser::SetPositionAndSize(int32_t aX, int32_t aY, + int32_t aCX, int32_t aCY, uint32_t aFlags) +{ + if (!mDocShell) { + mInitInfo->x = aX; + mInitInfo->y = aY; + mInitInfo->cx = aCX; + mInitInfo->cy = aCY; + } else { + int32_t doc_x = aX; + int32_t doc_y = aY; + + // If there is an internal widget we need to make the docShell coordinates + // relative to the internal widget rather than the calling app's parent. + // We also need to resize our widget then. + if (mInternalWidget) { + doc_x = doc_y = 0; + NS_ENSURE_SUCCESS(mInternalWidget->Resize(aX, aY, aCX, aCY, + !!(aFlags & nsIBaseWindow::eRepaint)), + NS_ERROR_FAILURE); + } + // Now reposition/ resize the doc + NS_ENSURE_SUCCESS( + mDocShellAsWin->SetPositionAndSize(doc_x, doc_y, aCX, aCY, aFlags), + NS_ERROR_FAILURE); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetPositionAndSize(int32_t* aX, int32_t* aY, + int32_t* aCX, int32_t* aCY) +{ + if (!mDocShell) { + if (aX) { + *aX = mInitInfo->x; + } + if (aY) { + *aY = mInitInfo->y; + } + if (aCX) { + *aCX = mInitInfo->cx; + } + if (aCY) { + *aCY = mInitInfo->cy; + } + } else if (mInternalWidget) { + LayoutDeviceIntRect bounds = mInternalWidget->GetBounds(); + + if (aX) { + *aX = bounds.x; + } + if (aY) { + *aY = bounds.y; + } + if (aCX) { + *aCX = bounds.width; + } + if (aCY) { + *aCY = bounds.height; + } + return NS_OK; + } else { + // Can directly return this as it is the + // same interface, thus same returns. + return mDocShellAsWin->GetPositionAndSize(aX, aY, aCX, aCY); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Repaint(bool aForce) +{ + NS_ENSURE_STATE(mDocShell); + // Can directly return this as it is the + // same interface, thus same returns. + return mDocShellAsWin->Repaint(aForce); +} + +NS_IMETHODIMP +nsWebBrowser::GetParentWidget(nsIWidget** aParentWidget) +{ + NS_ENSURE_ARG_POINTER(aParentWidget); + + *aParentWidget = mParentWidget; + + NS_IF_ADDREF(*aParentWidget); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetParentWidget(nsIWidget* aParentWidget) +{ + NS_ENSURE_STATE(!mDocShell); + + mParentWidget = aParentWidget; + if (mParentWidget) { + mParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET); + } else { + mParentNativeWindow = nullptr; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetParentNativeWindow(nativeWindow* aParentNativeWindow) +{ + NS_ENSURE_ARG_POINTER(aParentNativeWindow); + + *aParentNativeWindow = mParentNativeWindow; + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetParentNativeWindow(nativeWindow aParentNativeWindow) +{ + NS_ENSURE_STATE(!mDocShell); + + mParentNativeWindow = aParentNativeWindow; + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetNativeHandle(nsAString& aNativeHandle) +{ + // the nativeHandle should be accessed from nsIXULWindow + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsWebBrowser::GetVisibility(bool* aVisibility) +{ + NS_ENSURE_ARG_POINTER(aVisibility); + + if (!mDocShell) { + *aVisibility = mInitInfo->visible; + } else { + NS_ENSURE_SUCCESS(mDocShellAsWin->GetVisibility(aVisibility), + NS_ERROR_FAILURE); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetVisibility(bool aVisibility) +{ + if (!mDocShell) { + mInitInfo->visible = aVisibility; + } else { + NS_ENSURE_SUCCESS(mDocShellAsWin->SetVisibility(aVisibility), + NS_ERROR_FAILURE); + if (mInternalWidget) { + mInternalWidget->Show(aVisibility); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetEnabled(bool* aEnabled) +{ + if (mInternalWidget) { + *aEnabled = mInternalWidget->IsEnabled(); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWebBrowser::SetEnabled(bool aEnabled) +{ + if (mInternalWidget) { + return mInternalWidget->Enable(aEnabled); + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWebBrowser::GetMainWidget(nsIWidget** aMainWidget) +{ + NS_ENSURE_ARG_POINTER(aMainWidget); + + if (mInternalWidget) { + *aMainWidget = mInternalWidget; + } else { + *aMainWidget = mParentWidget; + } + + NS_IF_ADDREF(*aMainWidget); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocus() +{ + nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow(); + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); + + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return fm ? fm->SetFocusedWindow(window) : NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetTitle(char16_t** aTitle) +{ + NS_ENSURE_ARG_POINTER(aTitle); + NS_ENSURE_STATE(mDocShell); + + NS_ENSURE_SUCCESS(mDocShellAsWin->GetTitle(aTitle), NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetTitle(const char16_t* aTitle) +{ + NS_ENSURE_STATE(mDocShell); + + NS_ENSURE_SUCCESS(mDocShellAsWin->SetTitle(aTitle), NS_ERROR_FAILURE); + + return NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIScrollable +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetDefaultScrollbarPreferences(int32_t aScrollOrientation, + int32_t* aScrollbarPref) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsScrollable->GetDefaultScrollbarPreferences( + aScrollOrientation, aScrollbarPref); +} + +NS_IMETHODIMP +nsWebBrowser::SetDefaultScrollbarPreferences(int32_t aScrollOrientation, + int32_t aScrollbarPref) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsScrollable->SetDefaultScrollbarPreferences( + aScrollOrientation, aScrollbarPref); +} + +NS_IMETHODIMP +nsWebBrowser::GetScrollbarVisibility(bool* aVerticalVisible, + bool* aHorizontalVisible) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsScrollable->GetScrollbarVisibility(aVerticalVisible, + aHorizontalVisible); +} + +//***************************************************************************** +// nsWebBrowser::nsITextScroll +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::ScrollByLines(int32_t aNumLines) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsTextScroll->ScrollByLines(aNumLines); +} + +NS_IMETHODIMP +nsWebBrowser::ScrollByPages(int32_t aNumPages) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsTextScroll->ScrollByPages(aNumPages); +} + +//***************************************************************************** +// nsWebBrowser: Listener Helpers +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::SetDocShell(nsIDocShell* aDocShell) +{ + // We need to keep the docshell alive while we perform the changes, but we + // don't need to call any methods on it. + nsCOMPtr<nsIDocShell> kungFuDeathGrip(mDocShell); + mozilla::Unused << kungFuDeathGrip; + + if (aDocShell) { + NS_ENSURE_TRUE(!mDocShell, NS_ERROR_FAILURE); + + nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(aDocShell)); + nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(aDocShell)); + nsCOMPtr<nsIWebNavigation> nav(do_QueryInterface(aDocShell)); + nsCOMPtr<nsIScrollable> scrollable(do_QueryInterface(aDocShell)); + nsCOMPtr<nsITextScroll> textScroll(do_QueryInterface(aDocShell)); + nsCOMPtr<nsIWebProgress> progress(do_GetInterface(aDocShell)); + NS_ENSURE_TRUE(req && baseWin && nav && scrollable && textScroll && progress, + NS_ERROR_FAILURE); + + mDocShell = aDocShell; + mDocShellAsReq = req; + mDocShellAsWin = baseWin; + mDocShellAsNav = nav; + mDocShellAsScrollable = scrollable; + mDocShellAsTextScroll = textScroll; + mWebProgress = progress; + + // By default, do not allow DNS prefetch, so we don't break our frozen + // API. Embeddors who decide to enable it should do so manually. + mDocShell->SetAllowDNSPrefetch(false); + + // It's possible to call setIsActive() on us before we have a docshell. + // If we're getting a docshell now, pass along our desired value. The + // default here (true) matches the default of the docshell, so this is + // a no-op unless setIsActive(false) has been called on us. + mDocShell->SetIsActive(mIsActive); + } else { + if (mDocShellTreeOwner) { + mDocShellTreeOwner->RemoveFromWatcher(); // evil twin of Add in Create() + } + if (mDocShellAsWin) { + mDocShellAsWin->Destroy(); + } + + mDocShell = nullptr; + mDocShellAsReq = nullptr; + mDocShellAsWin = nullptr; + mDocShellAsNav = nullptr; + mDocShellAsScrollable = nullptr; + mDocShellAsTextScroll = nullptr; + mWebProgress = nullptr; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::EnsureDocShellTreeOwner() +{ + if (mDocShellTreeOwner) { + return NS_OK; + } + + mDocShellTreeOwner = new nsDocShellTreeOwner(); + mDocShellTreeOwner->WebBrowser(this); + + return NS_OK; +} + +static void +DrawPaintedLayer(PaintedLayer* aLayer, + gfxContext* aContext, + const nsIntRegion& aRegionToDraw, + const nsIntRegion& aDirtyRegion, + DrawRegionClip aClip, + const nsIntRegion& aRegionToInvalidate, + void* aCallbackData) +{ + DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); + + ColorPattern color(ToDeviceColor(*static_cast<nscolor*>(aCallbackData))); + nsIntRect dirtyRect = aRegionToDraw.GetBounds(); + aDrawTarget.FillRect( + Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height), color); +} + +void +nsWebBrowser::WindowRaised(nsIWidget* aWidget) +{ +#if defined(DEBUG_smaug) + nsCOMPtr<nsIDocument> document = mDocShell->GetDocument(); + nsAutoString documentURI; + document->GetDocumentURI(documentURI); + printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)this, + NS_ConvertUTF16toUTF8(documentURI).get()); +#endif + Activate(); +} + +void +nsWebBrowser::WindowLowered(nsIWidget* aWidget) +{ +#if defined(DEBUG_smaug) + nsCOMPtr<nsIDocument> document = mDocShell->GetDocument(); + nsAutoString documentURI; + document->GetDocumentURI(documentURI); + printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)this, + NS_ConvertUTF16toUTF8(documentURI).get()); +#endif + Deactivate(); +} + +bool +nsWebBrowser::PaintWindow(nsIWidget* aWidget, LayoutDeviceIntRegion aRegion) +{ + LayerManager* layerManager = aWidget->GetLayerManager(); + NS_ASSERTION(layerManager, "Must be in paint event"); + + layerManager->BeginTransaction(); + RefPtr<PaintedLayer> root = layerManager->CreatePaintedLayer(); + if (root) { + nsIntRect dirtyRect = aRegion.GetBounds().ToUnknownRect(); + root->SetVisibleRegion(LayerIntRegion::FromUnknownRegion(dirtyRect)); + layerManager->SetRoot(root); + } + + layerManager->EndTransaction(DrawPaintedLayer, &mBackgroundColor); + return true; +} +/* +NS_IMETHODIMP +nsWebBrowser::GetPrimaryContentWindow(mozIDOMWindowProxy** aDOMWindow) +{ + *aDOMWindow = nullptr; + + nsCOMPtr<nsIDocShellTreeItem> item; + NS_ENSURE_TRUE(mDocShellTreeOwner, NS_ERROR_FAILURE); + mDocShellTreeOwner->GetPrimaryContentShell(getter_AddRefs(item)); + NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); + + nsCOMPtr<nsIDocShell> docShell; + docShell = do_QueryInterface(item); + NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); + + nsCOMPtr<nsPIDOMWindowOuter> domWindow = docShell->GetWindow(); + NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE); + + *aDOMWindow = domWindow; + NS_ADDREF(*aDOMWindow); + return NS_OK; +} +*/ +//***************************************************************************** +// nsWebBrowser::nsIWebBrowserFocus +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::Activate(void) +{ + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow(); + if (fm && window) { + return fm->WindowRaised(window); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Deactivate(void) +{ + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow(); + if (fm && window) { + return fm->WindowLowered(window); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocusAtFirstElement(void) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocusAtLastElement(void) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetFocusedWindow(mozIDOMWindowProxy** aFocusedWindow) +{ + NS_ENSURE_ARG_POINTER(aFocusedWindow); + *aFocusedWindow = nullptr; + + NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + + nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell->GetWindow(); + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); + + nsCOMPtr<nsIDOMElement> focusedElement; + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return fm ? fm->GetFocusedElementForWindow(window, true, aFocusedWindow, + getter_AddRefs(focusedElement)) : + NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocusedWindow(mozIDOMWindowProxy* aFocusedWindow) +{ + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return fm ? fm->SetFocusedWindow(aFocusedWindow) : NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetFocusedElement(nsIDOMElement** aFocusedElement) +{ + NS_ENSURE_ARG_POINTER(aFocusedElement); + NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + + nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell->GetWindow(); + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); + + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return + fm ? fm->GetFocusedElementForWindow(window, true, nullptr, aFocusedElement) : + NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocusedElement(nsIDOMElement* aFocusedElement) +{ + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return fm ? fm->SetFocus(aFocusedElement, 0) : NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebBrowserStream +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::OpenStream(nsIURI* aBaseURI, const nsACString& aContentType) +{ + nsresult rv; + + if (!mStream) { + mStream = new nsEmbedStream(); + mStream->InitOwner(this); + rv = mStream->Init(); + if (NS_FAILED(rv)) { + return rv; + } + } + + return mStream->OpenStream(aBaseURI, aContentType); +} + + +NS_IMETHODIMP +nsWebBrowser::AppendToStream(const uint8_t* aData, uint32_t aLen) +{ + if (!mStream) { + return NS_ERROR_FAILURE; + } + + return mStream->AppendToStream(aData, aLen); +} + +NS_IMETHODIMP +nsWebBrowser::CloseStream() +{ + nsresult rv; + + if (!mStream) { + return NS_ERROR_FAILURE; + } + rv = mStream->CloseStream(); + + mStream = nullptr; + + return rv; +} + +bool +nsWebBrowser::WidgetListenerDelegate::PaintWindow( + nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) +{ + RefPtr<nsWebBrowser> holder = mWebBrowser; + return holder->PaintWindow(aWidget, aRegion); +} |