/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* 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" //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 "nsAutoPtr.h" #include "nsFocusManager.h" #include "Layers.h" #include "gfxContext.h" #include "nsILoadContext.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::layers; static NS_DEFINE_CID(kChildCID, NS_CHILD_CID); //***************************************************************************** //*** nsWebBrowser: Object Management //***************************************************************************** nsWebBrowser::nsWebBrowser() : mDocShellTreeOwner(nullptr), mInitInfo(nullptr), mContentType(typeContentWrapper), mActivating(false), mShouldEnableHistory(true), mIsActive(true), mParentNativeWindow(nullptr), mProgressListener(nullptr), mBackgroundColor(0), mPersistCurrentState(nsIWebBrowserPersist::PERSIST_STATE_READY), mPersistResult(NS_OK), mPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_NONE), mStream(nullptr), mParentWidget(nullptr), mListenerArray(nullptr) { mInitInfo = new nsWebBrowserInitInfo(); 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); NS_RELEASE(mDocShellTreeOwner); } if(mInitInfo) { delete mInitInfo; mInitInfo = nullptr; } if (mListenerArray) { for (uint32_t i = 0, end = mListenerArray->Length(); i < end; i++) { nsWebBrowserListenerState *state = mListenerArray->ElementAt(i); delete state; } delete mListenerArray; mListenerArray = nullptr; } return NS_OK; } //***************************************************************************** // nsWebBrowser::nsISupports //***************************************************************************** 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 viewer; mDocShell->GetContentViewer(getter_AddRefs(viewer)); if (!viewer) return NS_NOINTERFACE; nsCOMPtr 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. nsAutoPtr state; state = new nsWebBrowserListenerState(); if (!state) return NS_ERROR_OUT_OF_MEMORY; state->mWeakPtr = aListener; state->mID = aIID; if (!mListenerArray) { mListenerArray = new nsTArray(); if (!mListenerArray) { return NS_ERROR_OUT_OF_MEMORY; } } if (!mListenerArray->AppendElement(state)) { return NS_ERROR_OUT_OF_MEMORY; } // We're all set now; don't delete |state| after this point state.forget(); } else { nsCOMPtr 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 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 shistory(do_GetInterface(mDocShell, &rv)); if (NS_FAILED(rv)) return rv; nsCOMPtr 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) { nsWebBrowserListenerState *state = mListenerArray->ElementAt(count); NS_ASSERTION(state, "list construction problem"); if (state->Equals(aListener, aIID)) { // this is the one, pull it out. mListenerArray->RemoveElementAt(count); break; } count--; } // if we've emptied the array, get rid of it. if (0 >= mListenerArray->Length()) { for (uint32_t i = 0, end = mListenerArray->Length(); i < end; i++) { nsWebBrowserListenerState *state = mListenerArray->ElementAt(i); delete state; } delete mListenerArray; mListenerArray = nullptr; } } else { nsCOMPtr 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 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 shistory(do_GetInterface(mDocShell, &rv)); if (NS_FAILED(rv)) return rv; nsCOMPtr 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); if(mDocShellTreeOwner) { *aTopWindow = mDocShellTreeOwner->GetWebBrowserChrome().take(); } else { *aTopWindow = nullptr; } 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 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 listener(do_GetInterface(mDocShell)); if (listener) return listener->SetParentContentListener(aParentContentListener); return NS_ERROR_FAILURE; } NS_IMETHODIMP nsWebBrowser::GetContentDOMWindow(nsIDOMWindow **_retval) { NS_ENSURE_STATE(mDocShell); nsCOMPtr retval = mDocShell->GetWindow(); retval.forget(_retval); return *_retval ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP nsWebBrowser::GetIsActive(bool *rv) { *rv = 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; } //***************************************************************************** // 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 char16_t *aName, bool *_retval) { NS_ENSURE_ARG_POINTER(aName); NS_ENSURE_ARG_POINTER(_retval); if(mDocShell) { return mDocShell->NameEquals(aName, _retval); } else *_retval = 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(typeChrome) : static_cast(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(this); nsCOMPtr 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(this); nsCOMPtr 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 char16_t *aName, nsISupports* aRequestor, nsIDocShellTreeItem* aOriginalRequestor, nsIDocShellTreeItem **_retval) { NS_ENSURE_STATE(mDocShell); NS_ASSERTION(mDocShellTreeOwner, "This should always be set when in this situation"); return mDocShell->FindItemWithName(aName, static_cast(mDocShellTreeOwner), aOriginalRequestor, _retval); } nsIDocument* nsWebBrowser::GetDocument() { return mDocShell ? mDocShell->GetDocument() : nullptr; } nsPIDOMWindow* 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 char16_t * aName, bool aRecurse, bool aSameType, nsIDocShellTreeItem * aRequestor, nsIDocShellTreeItem * aOriginalRequestor, nsIDocShellTreeItem ** _retval) { NS_ENSURE_ARG_POINTER(_retval); *_retval = 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::LoadURIWithBase(const char16_t* aURI, uint32_t aLoadFlags, nsIURI* aReferringURI, nsIInputStream* aPostDataStream, nsIInputStream* aExtraHeaderStream, nsIURI* aBaseURI) { NS_ENSURE_STATE(mDocShell); return mDocShellAsNav->LoadURIWithBase(aURI, aLoadFlags, aReferringURI, aPostDataStream, aExtraHeaderStream, aBaseURI); } 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 //***************************************************************************** /* void setProperty (in unsigned long aId, in unsigned long aValue); */ 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(true) || aValue == static_cast(false)), NS_ERROR_INVALID_ARG); mDocShell->SetAllowPlugins(!!aValue); } break; case nsIWebBrowserSetup::SETUP_ALLOW_JAVASCRIPT: { NS_ENSURE_STATE(mDocShell); NS_ENSURE_TRUE((aValue == static_cast(true) || aValue == static_cast(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(true) || aValue == static_cast(false)), NS_ERROR_INVALID_ARG); mDocShell->SetAllowMetaRedirects(!!aValue); } break; case nsIWebBrowserSetup::SETUP_ALLOW_SUBFRAMES: { NS_ENSURE_STATE(mDocShell); NS_ENSURE_TRUE((aValue == static_cast(true) || aValue == static_cast(false)), NS_ERROR_INVALID_ARG); mDocShell->SetAllowSubframes(!!aValue); } break; case nsIWebBrowserSetup::SETUP_ALLOW_IMAGES: { NS_ENSURE_STATE(mDocShell); NS_ENSURE_TRUE((aValue == static_cast(true) || aValue == static_cast(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(true) || aValue == static_cast(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(true) || aValue == static_cast(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(true) || aValue == static_cast(false)), NS_ERROR_INVALID_ARG); SetItemType(aValue ? static_cast(typeChromeWrapper) : static_cast(typeContentWrapper)); } break; default: rv = NS_ERROR_INVALID_ARG; } return rv; } //***************************************************************************** // nsWebBrowser::nsIWebProgressListener //***************************************************************************** /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */ 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; } /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */ 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; } /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */ NS_IMETHODIMP nsWebBrowser::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags) { if (mProgressListener) { return mProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags); } return NS_OK; } /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */ 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; } /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */ NS_IMETHODIMP nsWebBrowser::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state) { if (mProgressListener) { return mProgressListener->OnSecurityChange(aWebProgress, aRequest, state); } return NS_OK; } //***************************************************************************** // nsWebBrowser::nsIWebBrowserPersist //***************************************************************************** /* attribute unsigned long persistFlags; */ 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; } /* readonly attribute unsigned long currentState; */ NS_IMETHODIMP nsWebBrowser::GetCurrentState(uint32_t *aCurrentState) { NS_ENSURE_ARG_POINTER(aCurrentState); if (mPersist) { mPersist->GetCurrentState(&mPersistCurrentState); } *aCurrentState = mPersistCurrentState; return NS_OK; } /* readonly attribute nsresult result; */ NS_IMETHODIMP nsWebBrowser::GetResult(nsresult *aResult) { NS_ENSURE_ARG_POINTER(aResult); if (mPersist) { mPersist->GetResult(&mPersistResult); } *aResult = mPersistResult; return NS_OK; } /* attribute nsIWebBrowserPersistProgress progressListener; */ 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; } /* void saveURI (in nsIURI aURI, in nsIURI aReferrer, in nsISupports aCacheKey, in nsIInputStream aPostData, in wstring aExtraHeaders, in nsISupports aFile, in nsILoadContext aPrivacyContext); */ NS_IMETHODIMP nsWebBrowser::SaveURI( nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer, nsIInputStream *aPostData, const char *aExtraHeaders, nsISupports *aFile, nsILoadContext* aPrivacyContext) { return SavePrivacyAwareURI(aURI, aCacheKey, aReferrer, aPostData, aExtraHeaders, aFile, aPrivacyContext && aPrivacyContext->UsePrivateBrowsing()); } NS_IMETHODIMP nsWebBrowser::SavePrivacyAwareURI( nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer, 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 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, aPostData, aExtraHeaders, aFile, aIsPrivate); if (NS_FAILED(rv)) { mPersist = nullptr; } return rv; } /* void saveChannel (in nsIChannel aChannel, in nsISupports aFile); */ 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; } /* void saveDocument (in nsIDOMDocument document, in nsISupports aFile, in nsISupports aDataPath); */ NS_IMETHODIMP nsWebBrowser::SaveDocument( nsIDOMDocument *aDocument, 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 doc; if (aDocument) { doc = do_QueryInterface(aDocument); } else { GetDocument(getter_AddRefs(doc)); } 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; } /* void cancelSave(); */ NS_IMETHODIMP nsWebBrowser::CancelSave() { if (mPersist) { return mPersist->CancelSave(); } return NS_OK; } /* void cancel(nsresult aReason); */ 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, false), 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 docShellParentWidget(mParentWidget); if(!mParentWidget) // We need to create a widget { // Create the widget mInternalWidget = do_CreateInstance(kChildCID, &rv); NS_ENSURE_SUCCESS(rv, rv); docShellParentWidget = mInternalWidget; nsWidgetInitData widgetInit; widgetInit.clipChildren = true; widgetInit.mWindowType = eWindowType_child; nsIntRect bounds(mInitInfo->x, mInitInfo->y, mInitInfo->cx, mInitInfo->cy); mInternalWidget->SetWidgetListener(this); mInternalWidget->Create(nullptr, mParentNativeWindow, bounds, nullptr, &widgetInit); } nsCOMPtr docShell(do_CreateInstance("@mozilla.org/docshell;1", &rv)); NS_ENSURE_SUCCESS(rv, rv); 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); NS_ASSERTION(state, "array construction problem"); nsCOMPtr listener = do_QueryReferent(state->mWeakPtr); NS_ASSERTION(listener, "bad listener"); (void)BindListener(listener, state->mID); i++; } for (uint32_t i = 0, end = mListenerArray->Length(); i < end; i++) { nsWebBrowserListenerState *state = mListenerArray->ElementAt(i); delete state; } delete mListenerArray; 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 supports = nullptr; (void)mDocShellTreeOwner->QueryInterface(NS_GET_IID(nsIWebProgressListener), static_cast(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_GetProcessType() == GeckoProcessType_Default) { // Hook up global history. Do not fail if we can't - just warn. rv = EnableGlobalHistory(mShouldEnableHistory); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "EnableGlobalHistory() failed"); } NS_ENSURE_SUCCESS(mDocShellAsWin->Create(), NS_ERROR_FAILURE); // Hook into the OnSecurityChange() notification for lock/unlock icon // updates nsCOMPtr 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 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(); delete mInitInfo; 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::SetPosition(int32_t aX, int32_t aY) { int32_t cx = 0; int32_t cy = 0; GetSize(&cx, &cy); return SetPositionAndSize(aX, aY, cx, cy, false); } 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); } 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, bool aRepaint) { 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, aRepaint), NS_ERROR_FAILURE); } // Now reposition/ resize the doc NS_ENSURE_SUCCESS(mDocShellAsWin->SetPositionAndSize(doc_x, doc_y, aCX, aCY, aRepaint), 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) { nsIntRect bounds; NS_ENSURE_SUCCESS(mInternalWidget->GetBounds(bounds), NS_ERROR_FAILURE); if(aX) *aX = bounds.x; if(aY) *aY = bounds.y; if(aCX) *aCX = bounds.width; if(aCY) *aCY = bounds.height; return NS_OK; } else return mDocShellAsWin->GetPositionAndSize(aX, aY, aCX, aCY); // Can directly return this as it is the } return NS_OK; } NS_IMETHODIMP nsWebBrowser::Repaint(bool aForce) { NS_ENSURE_STATE(mDocShell); return mDocShellAsWin->Repaint(aForce); // Can directly return this as it is the } // same interface, thus same returns. 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* visibility) { NS_ENSURE_ARG_POINTER(visibility); if(!mDocShell) *visibility = mInitInfo->visible; else NS_ENSURE_SUCCESS(mDocShellAsWin->GetVisibility(visibility), 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** mainWidget) { NS_ENSURE_ARG_POINTER(mainWidget); if(mInternalWidget) *mainWidget = mInternalWidget; else *mainWidget = mParentWidget; NS_IF_ADDREF(*mainWidget); return NS_OK; } NS_IMETHODIMP nsWebBrowser::SetFocus() { nsCOMPtr window = GetWindow(); NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); nsCOMPtr 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) { nsCOMPtr kungFuDeathGrip(mDocShell); if(aDocShell) { NS_ENSURE_TRUE(!mDocShell, NS_ERROR_FAILURE); nsCOMPtr req(do_QueryInterface(aDocShell)); nsCOMPtr baseWin(do_QueryInterface(aDocShell)); nsCOMPtr nav(do_QueryInterface(aDocShell)); nsCOMPtr scrollable(do_QueryInterface(aDocShell)); nsCOMPtr textScroll(do_QueryInterface(aDocShell)); nsCOMPtr 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(); NS_ENSURE_TRUE(mDocShellTreeOwner, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(mDocShellTreeOwner); mDocShellTreeOwner->WebBrowser(this); return NS_OK; } static void DrawPaintedLayer(PaintedLayer* aLayer, gfxContext* aContext, const nsIntRegion& aRegionToDraw, DrawRegionClip aClip, const nsIntRegion& aRegionToInvalidate, void* aCallbackData) { nscolor* color = static_cast(aCallbackData); aContext->NewPath(); aContext->SetColor(gfxRGBA(*color)); nsIntRect dirtyRect = aRegionToDraw.GetBounds(); aContext->Rectangle(gfxRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height)); aContext->Fill(); } void nsWebBrowser::WindowRaised(nsIWidget* aWidget) { #if defined(DEBUG_smaug) nsCOMPtr 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 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, nsIntRegion aRegion) { LayerManager* layerManager = aWidget->GetLayerManager(); NS_ASSERTION(layerManager, "Must be in paint event"); layerManager->BeginTransaction(); nsRefPtr root = layerManager->CreatePaintedLayer(); if (root) { nsIntRect dirtyRect = aRegion.GetBounds(); root->SetVisibleRegion(dirtyRect); layerManager->SetRoot(root); } layerManager->EndTransaction(DrawPaintedLayer, &mBackgroundColor); return true; } NS_IMETHODIMP nsWebBrowser::GetPrimaryContentWindow(nsIDOMWindow** aDOMWindow) { *aDOMWindow = 0; nsCOMPtr item; NS_ENSURE_TRUE(mDocShellTreeOwner, NS_ERROR_FAILURE); mDocShellTreeOwner->GetPrimaryContentShell(getter_AddRefs(item)); NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); nsCOMPtr docShell; docShell = do_QueryInterface(item); NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); nsCOMPtr domWindow = docShell->GetWindow(); NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE); *aDOMWindow = domWindow; NS_ADDREF(*aDOMWindow); return NS_OK; } //***************************************************************************** // nsWebBrowser::nsIWebBrowserFocus //***************************************************************************** /* void activate (); */ NS_IMETHODIMP nsWebBrowser::Activate(void) { nsCOMPtr fm = do_GetService(FOCUSMANAGER_CONTRACTID); nsCOMPtr window = GetWindow(); if (fm && window) return fm->WindowRaised(window); return NS_OK; } /* void deactivate (); */ NS_IMETHODIMP nsWebBrowser::Deactivate(void) { nsCOMPtr fm = do_GetService(FOCUSMANAGER_CONTRACTID); nsCOMPtr window = GetWindow(); if (fm && window) return fm->WindowLowered(window); return NS_OK; } /* void setFocusAtFirstElement (); */ NS_IMETHODIMP nsWebBrowser::SetFocusAtFirstElement(void) { return NS_OK; } /* void setFocusAtLastElement (); */ NS_IMETHODIMP nsWebBrowser::SetFocusAtLastElement(void) { return NS_OK; } /* attribute nsIDOMWindow focusedWindow; */ NS_IMETHODIMP nsWebBrowser::GetFocusedWindow(nsIDOMWindow * *aFocusedWindow) { NS_ENSURE_ARG_POINTER(aFocusedWindow); *aFocusedWindow = nullptr; NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); nsCOMPtr window = mDocShell->GetWindow(); NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); nsCOMPtr focusedElement; nsCOMPtr fm = do_GetService(FOCUSMANAGER_CONTRACTID); return fm ? fm->GetFocusedElementForWindow(window, true, aFocusedWindow, getter_AddRefs(focusedElement)) : NS_OK; } NS_IMETHODIMP nsWebBrowser::SetFocusedWindow(nsIDOMWindow * aFocusedWindow) { nsCOMPtr fm = do_GetService(FOCUSMANAGER_CONTRACTID); return fm ? fm->SetFocusedWindow(aFocusedWindow) : NS_OK; } /* attribute nsIDOMElement focusedElement; */ NS_IMETHODIMP nsWebBrowser::GetFocusedElement(nsIDOMElement * *aFocusedElement) { NS_ENSURE_ARG_POINTER(aFocusedElement); NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); nsCOMPtr window = mDocShell->GetWindow(); NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); nsCOMPtr fm = do_GetService(FOCUSMANAGER_CONTRACTID); return fm ? fm->GetFocusedElementForWindow(window, true, nullptr, aFocusedElement) : NS_OK; } NS_IMETHODIMP nsWebBrowser::SetFocusedElement(nsIDOMElement * aFocusedElement) { nsCOMPtr fm = do_GetService(FOCUSMANAGER_CONTRACTID); return fm ? fm->SetFocus(aFocusedElement, 0) : NS_OK; } //***************************************************************************** // nsWebBrowser::nsIWebBrowserStream //***************************************************************************** /* void openStream(in nsIURI aBaseURI, in ACString aContentType); */ NS_IMETHODIMP nsWebBrowser::OpenStream(nsIURI *aBaseURI, const nsACString& aContentType) { nsresult rv; if (!mStream) { mStream = new nsEmbedStream(); if (!mStream) return NS_ERROR_OUT_OF_MEMORY; mStreamGuard = do_QueryInterface(mStream); mStream->InitOwner(this); rv = mStream->Init(); if (NS_FAILED(rv)) return rv; } return mStream->OpenStream(aBaseURI, aContentType); } /* void appendToStream([const, array, size_is(aLen)] in octet aData, * in unsigned long aLen); */ NS_IMETHODIMP nsWebBrowser::AppendToStream(const uint8_t *aData, uint32_t aLen) { if (!mStream) return NS_ERROR_FAILURE; return mStream->AppendToStream(aData, aLen); } /* void closeStream (); */ NS_IMETHODIMP nsWebBrowser::CloseStream() { nsresult rv; if (!mStream) return NS_ERROR_FAILURE; rv = mStream->CloseStream(); // release mStream = 0; mStreamGuard = 0; return rv; }