forked from mirrors/gecko-dev
In bug 1773342 I made OS text scale factor behave like a full zoom factor which applies to all pages (including the browser chrome). That's generally straight forward but it makes some callsites that use unzoomed CSS coordinates misbehave (or behave correctly accidentally actually in some other cases). The main fix here is making nsIBaseWindow::UnscaledDevicePixelsPerCSSPixel() and nsIScreen::GetDefaultCSSScaleFactor() account for OS zoom as necessary. However, I also went through the relevant code and cleaned it up to use typed units and operations when possible. The setup means: * nsIWidget::GetDefaultScale() doesn't account for OS full zoom. * nsIBaseWindow and nsIScreen does. These are the places where this should matter and stuff can get confused, but this works surprisingly well for all callers (except one nsDeviceContext one which we use only for PuppetWidget and we can remove by falling back to 1.0 like all other widgets until the update comes). Differential Revision: https://phabricator.services.mozilla.com/D149033
1215 lines
34 KiB
C++
1215 lines
34 KiB
C++
/* -*- 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 "gfxContext.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsIInterfaceRequestor.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "nsIWebBrowserChrome.h"
|
|
#include "nsPIDOMWindow.h"
|
|
#include "nsIWebProgress.h"
|
|
#include "nsIWebProgressListener.h"
|
|
#include "nsIURI.h"
|
|
#include "nsIWebBrowserPersist.h"
|
|
#include "nsFocusManager.h"
|
|
#include "Layers.h"
|
|
#include "nsILoadContext.h"
|
|
#include "nsComponentManagerUtils.h"
|
|
#include "nsDocShell.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "WindowRenderer.h"
|
|
|
|
#include "mozilla/dom/Element.h"
|
|
#include "mozilla/dom/BrowsingContext.h"
|
|
#include "mozilla/dom/LoadURIOptionsBinding.h"
|
|
#include "mozilla/dom/WindowGlobalChild.h"
|
|
|
|
// for painting the background window
|
|
#include "mozilla/LookAndFeel.h"
|
|
#include "mozilla/ServoStyleConsts.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;
|
|
|
|
nsWebBrowser::nsWebBrowser(int aItemType)
|
|
: mContentType(aItemType),
|
|
mShouldEnableHistory(true),
|
|
mWillChangeProcess(false),
|
|
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(); }
|
|
|
|
nsIWidget* nsWebBrowser::EnsureWidget() {
|
|
if (mParentWidget) {
|
|
return mParentWidget;
|
|
}
|
|
|
|
mInternalWidget = nsIWidget::CreateChildWindow();
|
|
if (NS_WARN_IF(!mInternalWidget)) {
|
|
return nullptr;
|
|
}
|
|
|
|
nsWidgetInitData widgetInit;
|
|
widgetInit.mClipChildren = true;
|
|
widgetInit.mWindowType = eWindowType_child;
|
|
LayoutDeviceIntRect bounds(0, 0, 0, 0);
|
|
|
|
mInternalWidget->SetWidgetListener(&mWidgetListenerDelegate);
|
|
NS_ENSURE_SUCCESS(mInternalWidget->Create(nullptr, mParentNativeWindow,
|
|
bounds, &widgetInit),
|
|
nullptr);
|
|
|
|
return mInternalWidget;
|
|
}
|
|
|
|
/* static */
|
|
already_AddRefed<nsWebBrowser> nsWebBrowser::Create(
|
|
nsIWebBrowserChrome* aContainerWindow, nsIWidget* aParentWidget,
|
|
dom::BrowsingContext* aBrowsingContext,
|
|
dom::WindowGlobalChild* aInitialWindowChild) {
|
|
MOZ_ASSERT_IF(aInitialWindowChild,
|
|
aInitialWindowChild->BrowsingContext() == aBrowsingContext);
|
|
|
|
RefPtr<nsWebBrowser> browser = new nsWebBrowser(
|
|
aBrowsingContext->IsContent() ? typeContentWrapper : typeChromeWrapper);
|
|
|
|
// nsWebBrowser::SetContainer also calls nsWebBrowser::EnsureDocShellTreeOwner
|
|
NS_ENSURE_SUCCESS(browser->SetContainerWindow(aContainerWindow), nullptr);
|
|
NS_ENSURE_SUCCESS(browser->SetParentWidget(aParentWidget), nullptr);
|
|
|
|
nsCOMPtr<nsIWidget> docShellParentWidget = browser->EnsureWidget();
|
|
if (NS_WARN_IF(!docShellParentWidget)) {
|
|
return nullptr;
|
|
}
|
|
|
|
uint64_t outerWindowId =
|
|
aInitialWindowChild ? aInitialWindowChild->OuterWindowId() : 0;
|
|
|
|
RefPtr<nsDocShell> docShell =
|
|
nsDocShell::Create(aBrowsingContext, outerWindowId);
|
|
if (NS_WARN_IF(!docShell)) {
|
|
return nullptr;
|
|
}
|
|
browser->SetDocShell(docShell);
|
|
MOZ_ASSERT(browser->mDocShell == docShell);
|
|
|
|
// get the system default window background colour
|
|
//
|
|
// TODO(emilio): Can we get the color-scheme from somewhere here?
|
|
browser->mBackgroundColor =
|
|
LookAndFeel::Color(LookAndFeel::ColorID::Window, ColorScheme::Light,
|
|
LookAndFeel::UseStandins::No);
|
|
|
|
// 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.
|
|
RefPtr<nsDocShellTreeOwner> docShellTreeOwner = browser->mDocShellTreeOwner;
|
|
Unused << docShell->AddProgressListener(docShellTreeOwner,
|
|
nsIWebProgress::NOTIFY_ALL);
|
|
|
|
docShell->SetTreeOwner(docShellTreeOwner);
|
|
|
|
// 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.
|
|
|
|
nsresult rv = docShell->InitWindow(nullptr, docShellParentWidget, 0, 0, 0, 0);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return nullptr;
|
|
}
|
|
|
|
docShellTreeOwner->AddToWatcher(); // evil twin of Remove in SetDocShell(0)
|
|
docShellTreeOwner->AddChromeListeners();
|
|
|
|
if (aInitialWindowChild) {
|
|
docShell->CreateContentViewerForActor(aInitialWindowChild);
|
|
}
|
|
|
|
return browser.forget();
|
|
}
|
|
|
|
void nsWebBrowser::InternalDestroy() {
|
|
if (mInternalWidget) {
|
|
mInternalWidget->SetWidgetListener(nullptr);
|
|
mInternalWidget->Destroy();
|
|
mInternalWidget = nullptr; // Force release here.
|
|
}
|
|
|
|
SetDocShell(nullptr);
|
|
|
|
if (mDocShellTreeOwner) {
|
|
mDocShellTreeOwner->WebBrowser(nullptr);
|
|
mDocShellTreeOwner = nullptr;
|
|
}
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsWebBrowser)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsWebBrowser)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_WEAK(nsWebBrowser, mDocShell)
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(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(nsIDocShellTreeItem)
|
|
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
|
|
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersist)
|
|
NS_INTERFACE_MAP_ENTRY(nsICancelable)
|
|
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
|
|
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 mDocShell->GetInterface(aIID, aSink);
|
|
}
|
|
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// nsWebBrowser::nsIWebBrowser
|
|
//*****************************************************************************
|
|
|
|
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) {
|
|
EnsureDocShellTreeOwner();
|
|
return mDocShellTreeOwner->SetWebBrowserChrome(aTopWindow);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void nsWebBrowser::SetOriginAttributes(const OriginAttributes& aAttrs) {
|
|
mOriginAttributes = aAttrs;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// nsWebBrowser::nsIDocShellTreeItem
|
|
//*****************************************************************************
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetName(nsAString& aName) {
|
|
if (mDocShell) {
|
|
mDocShell->GetName(aName);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::SetName(const nsAString& aName) {
|
|
if (mDocShell) {
|
|
return mDocShell->SetName(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);
|
|
}
|
|
|
|
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::GetInProcessParent(nsIDocShellTreeItem** aParent) {
|
|
*aParent = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
|
|
*aParent = nullptr;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
|
|
NS_ENSURE_ARG_POINTER(aRootTreeItem);
|
|
*aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parent;
|
|
NS_ENSURE_SUCCESS(GetInProcessParent(getter_AddRefs(parent)),
|
|
NS_ERROR_FAILURE);
|
|
while (parent) {
|
|
*aRootTreeItem = parent;
|
|
NS_ENSURE_SUCCESS(
|
|
(*aRootTreeItem)->GetInProcessParent(getter_AddRefs(parent)),
|
|
NS_ERROR_FAILURE);
|
|
}
|
|
NS_ADDREF(*aRootTreeItem);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetInProcessSameTypeRootTreeItem(
|
|
nsIDocShellTreeItem** aRootTreeItem) {
|
|
NS_ENSURE_ARG_POINTER(aRootTreeItem);
|
|
*aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parent;
|
|
NS_ENSURE_SUCCESS(GetInProcessSameTypeParent(getter_AddRefs(parent)),
|
|
NS_ERROR_FAILURE);
|
|
while (parent) {
|
|
*aRootTreeItem = parent;
|
|
NS_ENSURE_SUCCESS(
|
|
(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent)),
|
|
NS_ERROR_FAILURE);
|
|
}
|
|
NS_ADDREF(*aRootTreeItem);
|
|
return NS_OK;
|
|
}
|
|
|
|
dom::Document* nsWebBrowser::GetDocument() {
|
|
return mDocShell ? mDocShell->GetDocument() : nullptr;
|
|
}
|
|
|
|
nsPIDOMWindowOuter* nsWebBrowser::GetWindow() {
|
|
return mDocShell ? mDocShell->GetWindow() : nullptr;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetBrowsingContextXPCOM(dom::BrowsingContext** aBrowsingContext) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
return mDocShell->GetBrowsingContextXPCOM(aBrowsingContext);
|
|
}
|
|
|
|
dom::BrowsingContext* nsWebBrowser::GetBrowsingContext() {
|
|
return mDocShell->GetBrowsingContext();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetDomWindow(mozIDOMWindowProxy** aWindow) {
|
|
if (!mDocShell) return NS_ERROR_NOT_INITIALIZED;
|
|
return mDocShell->GetDomWindow(aWindow);
|
|
}
|
|
|
|
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) {
|
|
EnsureDocShellTreeOwner();
|
|
return mDocShellTreeOwner->SetTreeOwner(aTreeOwner);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// nsWebBrowser::nsIDocShellTreeItem
|
|
//*****************************************************************************
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetInProcessChildCount(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::GetInProcessChildAt(int32_t aIndex,
|
|
nsIDocShellTreeItem** aChild) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// nsWebBrowser::nsIWebNavigation
|
|
//*****************************************************************************
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetCanGoBack(bool* aCanGoBack) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->GetCanGoBack(aCanGoBack);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetCanGoForward(bool* aCanGoForward) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->GetCanGoForward(aCanGoForward);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->GoBack(aRequireUserInteraction, aUserActivation);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->GoForward(aRequireUserInteraction, aUserActivation);
|
|
}
|
|
|
|
nsresult nsWebBrowser::LoadURI(const nsAString& aURI,
|
|
const dom::LoadURIOptions& aLoadURIOptions) {
|
|
#ifndef ANDROID
|
|
MOZ_ASSERT(aLoadURIOptions.mTriggeringPrincipal,
|
|
"nsWebBrowser::LoadURI - Need a valid triggeringPrincipal");
|
|
#endif
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->LoadURI(aURI, aLoadURIOptions);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::LoadURIFromScript(const nsAString& aURI,
|
|
JS::Handle<JS::Value> aLoadURIOptions,
|
|
JSContext* aCx) {
|
|
// generate dictionary for loadURIOptions and forward call
|
|
dom::LoadURIOptions loadURIOptions;
|
|
if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
return LoadURI(aURI, loadURIOptions);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::ResumeRedirectedLoad(uint64_t aIdentifier,
|
|
int32_t aHistoryIndex) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->ResumeRedirectedLoad(aIdentifier, aHistoryIndex);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::Reload(uint32_t aReloadFlags) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->Reload(aReloadFlags);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GotoIndex(int32_t aIndex, bool aUserActivation) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->GotoIndex(aIndex, aUserActivation);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::Stop(uint32_t aStopFlags) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->Stop(aStopFlags);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetCurrentURI(nsIURI** aURI) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->GetCurrentURI(aURI);
|
|
}
|
|
|
|
// XXX(nika): Consider making the mozilla::dom::ChildSHistory version the
|
|
// canonical one?
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
|
|
NS_ENSURE_ARG_POINTER(aSessionHistory);
|
|
*aSessionHistory = nullptr;
|
|
if (mDocShell) {
|
|
return mDocShell->GetSessionHistoryXPCOM(aSessionHistory);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetDocument(dom::Document** aDocument) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
return mDocShell->GetDocument(aDocument);
|
|
}
|
|
|
|
void nsWebBrowser::SetAllowDNSPrefetch(bool aAllowPrefetch) {
|
|
MOZ_ASSERT(mDocShell);
|
|
mDocShell->SetAllowDNSPrefetch(aAllowPrefetch);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// 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;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
|
|
nsIRequest* aRequest, uint32_t aEvent) {
|
|
if (mProgressListener) {
|
|
return mProgressListener->OnContentBlockingEvent(aWebProgress, aRequest,
|
|
aEvent);
|
|
}
|
|
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, nsIPrincipal* aPrincipal,
|
|
uint32_t aCacheKey, nsIReferrerInfo* aReferrerInfo,
|
|
nsICookieJarSettings* aCookieJarSettings,
|
|
nsIInputStream* aPostData, const char* aExtraHeaders,
|
|
nsISupports* aFile,
|
|
nsContentPolicyType aContentPolicyType,
|
|
nsILoadContext* aPrivacyContext) {
|
|
return SavePrivacyAwareURI(
|
|
aURI, aPrincipal, aCacheKey, aReferrerInfo, aCookieJarSettings, aPostData,
|
|
aExtraHeaders, aFile, aContentPolicyType,
|
|
aPrivacyContext && aPrivacyContext->UsePrivateBrowsing());
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::SavePrivacyAwareURI(
|
|
nsIURI* aURI, nsIPrincipal* aPrincipal, uint32_t aCacheKey,
|
|
nsIReferrerInfo* aReferrerInfo, nsICookieJarSettings* aCookieJarSettings,
|
|
nsIInputStream* aPostData, const char* aExtraHeaders, nsISupports* aFile,
|
|
nsContentPolicyType aContentPolicyType, 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, aPrincipal, aCacheKey, aReferrerInfo, aCookieJarSettings, aPostData,
|
|
aExtraHeaders, aFile, aContentPolicyType, 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 {
|
|
RefPtr<dom::Document> domDoc;
|
|
GetDocument(getter_AddRefs(domDoc));
|
|
doc = already_AddRefed<nsISupports>(ToSupports(domDoc.forget().take()));
|
|
}
|
|
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);
|
|
RefPtr<nsIWebBrowserPersist> localPersist(mPersist);
|
|
Unused << localPersist;
|
|
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) {
|
|
// nsIBaseWindow::InitWindow and nsIBaseWindow::Create
|
|
// implementations have been merged into nsWebBrowser::Create
|
|
MOZ_DIAGNOSTIC_ASSERT(false);
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::Destroy() {
|
|
InternalDestroy();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
double nsWebBrowser::GetWidgetCSSToDeviceScale() {
|
|
return mParentWidget ? mParentWidget->GetDefaultScale().scale : 1.0;
|
|
}
|
|
|
|
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) {
|
|
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;
|
|
mInternalWidget->Resize(aX, aY, aCX, aCY,
|
|
!!(aFlags & nsIBaseWindow::eRepaint));
|
|
}
|
|
// Now reposition/ resize the doc
|
|
NS_ENSURE_SUCCESS(
|
|
mDocShell->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 (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 mDocShell->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 mDocShell->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 nsIAppWindow
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::GetVisibility(bool* aVisibility) {
|
|
NS_ENSURE_ARG_POINTER(aVisibility);
|
|
|
|
if (mDocShell) {
|
|
NS_ENSURE_SUCCESS(mDocShell->GetVisibility(aVisibility), NS_ERROR_FAILURE);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::SetVisibility(bool aVisibility) {
|
|
if (mDocShell) {
|
|
NS_ENSURE_SUCCESS(mDocShell->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) {
|
|
mInternalWidget->Enable(aEnabled);
|
|
return NS_OK;
|
|
}
|
|
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::GetTitle(nsAString& aTitle) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
NS_ENSURE_SUCCESS(mDocShell->GetTitle(aTitle), NS_ERROR_FAILURE);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWebBrowser::SetTitle(const nsAString& aTitle) {
|
|
NS_ENSURE_STATE(mDocShell);
|
|
|
|
NS_ENSURE_SUCCESS(mDocShell->SetTitle(aTitle), NS_ERROR_FAILURE);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// nsWebBrowser: Listener Helpers
|
|
//*****************************************************************************
|
|
|
|
void nsWebBrowser::SetDocShell(nsDocShell* 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) {
|
|
MOZ_ASSERT(!mDocShell, "Should not overwrite an existing value!");
|
|
|
|
mDocShell = aDocShell;
|
|
|
|
// 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);
|
|
} else {
|
|
if (mDocShellTreeOwner) {
|
|
mDocShellTreeOwner->RemoveFromWatcher(); // evil twin of Add in Create()
|
|
}
|
|
if (mDocShell) {
|
|
mDocShell->Destroy();
|
|
}
|
|
if (!mWillChangeProcess && mDocShell) {
|
|
mDocShell->GetBrowsingContext()->Detach(/* aFromIPC */ true);
|
|
}
|
|
|
|
mDocShell = nullptr;
|
|
}
|
|
}
|
|
|
|
void nsWebBrowser::EnsureDocShellTreeOwner() {
|
|
if (mDocShellTreeOwner) {
|
|
return;
|
|
}
|
|
|
|
mDocShellTreeOwner = new nsDocShellTreeOwner();
|
|
mDocShellTreeOwner->WebBrowser(this);
|
|
}
|
|
|
|
void nsWebBrowser::WindowActivated() {
|
|
#if defined(DEBUG_smaug)
|
|
RefPtr<dom::Document> document = mDocShell->GetDocument();
|
|
nsAutoString documentURI;
|
|
document->GetDocumentURI(documentURI);
|
|
printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)this,
|
|
NS_ConvertUTF16toUTF8(documentURI).get());
|
|
#endif
|
|
FocusActivate(nsFocusManager::GenerateFocusActionId());
|
|
}
|
|
|
|
void nsWebBrowser::WindowDeactivated() {
|
|
#if defined(DEBUG_smaug)
|
|
RefPtr<dom::Document> document = mDocShell->GetDocument();
|
|
nsAutoString documentURI;
|
|
document->GetDocumentURI(documentURI);
|
|
printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)this,
|
|
NS_ConvertUTF16toUTF8(documentURI).get());
|
|
#endif
|
|
FocusDeactivate(nsFocusManager::GenerateFocusActionId());
|
|
}
|
|
|
|
bool nsWebBrowser::PaintWindow(nsIWidget* aWidget,
|
|
LayoutDeviceIntRegion aRegion) {
|
|
WindowRenderer* renderer = aWidget->GetWindowRenderer();
|
|
NS_ASSERTION(renderer, "Must be in paint event");
|
|
if (FallbackRenderer* fallback = renderer->AsFallback()) {
|
|
if (fallback->BeginTransaction()) {
|
|
fallback->EndTransactionWithColor(aRegion.GetBounds().ToUnknownRect(),
|
|
ToDeviceColor(mBackgroundColor));
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void nsWebBrowser::FocusActivate(uint64_t aActionId) {
|
|
if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
|
|
if (nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow()) {
|
|
fm->WindowRaised(window, aActionId);
|
|
}
|
|
}
|
|
}
|
|
|
|
void nsWebBrowser::FocusDeactivate(uint64_t aActionId) {
|
|
if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
|
|
if (nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow()) {
|
|
fm->WindowLowered(window, aActionId);
|
|
}
|
|
}
|
|
}
|
|
|
|
void nsWebBrowser::SetWillChangeProcess() {
|
|
mWillChangeProcess = true;
|
|
if (mDocShell) {
|
|
nsDocShell::Cast(mDocShell)->SetWillChangeProcess();
|
|
}
|
|
}
|
|
|
|
void nsWebBrowser::WidgetListenerDelegate::WindowActivated() {
|
|
RefPtr<nsWebBrowser> holder = mWebBrowser;
|
|
holder->WindowActivated();
|
|
}
|
|
|
|
void nsWebBrowser::WidgetListenerDelegate::WindowDeactivated() {
|
|
RefPtr<nsWebBrowser> holder = mWebBrowser;
|
|
holder->WindowDeactivated();
|
|
}
|
|
|
|
bool nsWebBrowser::WidgetListenerDelegate::PaintWindow(
|
|
nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) {
|
|
RefPtr<nsWebBrowser> holder = mWebBrowser;
|
|
return holder->PaintWindow(aWidget, aRegion);
|
|
}
|