From 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:47:29 +0200 Subject: Adding upstream version 115.8.0esr. Signed-off-by: Daniel Baumann --- toolkit/components/browser/build/components.conf | 15 + toolkit/components/browser/build/moz.build | 11 + toolkit/components/browser/moz.build | 41 + toolkit/components/browser/nsEmbedCID.h | 44 + .../browser/nsIPrintPreviewNavigation.idl | 52 + toolkit/components/browser/nsIWebBrowser.idl | 81 ++ toolkit/components/browser/nsIWebBrowserChrome.idl | 142 +++ .../browser/nsIWebBrowserChromeFocus.idl | 32 + toolkit/components/browser/nsIWebBrowserPrint.idl | 129 ++ toolkit/components/browser/nsWebBrowser.cpp | 1241 ++++++++++++++++++++ toolkit/components/browser/nsWebBrowser.h | 164 +++ .../browser/nsWebBrowserContentPolicy.cpp | 87 ++ .../components/browser/nsWebBrowserContentPolicy.h | 29 + 13 files changed, 2068 insertions(+) create mode 100644 toolkit/components/browser/build/components.conf create mode 100644 toolkit/components/browser/build/moz.build create mode 100644 toolkit/components/browser/moz.build create mode 100644 toolkit/components/browser/nsEmbedCID.h create mode 100644 toolkit/components/browser/nsIPrintPreviewNavigation.idl create mode 100644 toolkit/components/browser/nsIWebBrowser.idl create mode 100644 toolkit/components/browser/nsIWebBrowserChrome.idl create mode 100644 toolkit/components/browser/nsIWebBrowserChromeFocus.idl create mode 100644 toolkit/components/browser/nsIWebBrowserPrint.idl create mode 100644 toolkit/components/browser/nsWebBrowser.cpp create mode 100644 toolkit/components/browser/nsWebBrowser.h create mode 100644 toolkit/components/browser/nsWebBrowserContentPolicy.cpp create mode 100644 toolkit/components/browser/nsWebBrowserContentPolicy.h (limited to 'toolkit/components/browser') diff --git a/toolkit/components/browser/build/components.conf b/toolkit/components/browser/build/components.conf new file mode 100644 index 0000000000..a0bdb1303c --- /dev/null +++ b/toolkit/components/browser/build/components.conf @@ -0,0 +1,15 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +Classes = [ + { + 'cid': '{f66bc334-1dd1-11b2-bab2-90e04fe15c19}', + 'contract_ids': ['@mozilla.org/embedding/browser/content-policy;1'], + 'type': 'nsWebBrowserContentPolicy', + 'headers': ['/toolkit/components/browser/nsWebBrowserContentPolicy.h'], + 'categories': {'content-policy': '@mozilla.org/embedding/browser/content-policy;1'}, + }, +] diff --git a/toolkit/components/browser/build/moz.build b/toolkit/components/browser/build/moz.build new file mode 100644 index 0000000000..64df8d564c --- /dev/null +++ b/toolkit/components/browser/build/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +XPCOM_MANIFESTS += [ + "components.conf", +] + +FINAL_LIBRARY = "xul" diff --git a/toolkit/components/browser/moz.build b/toolkit/components/browser/moz.build new file mode 100644 index 0000000000..903390a3c8 --- /dev/null +++ b/toolkit/components/browser/moz.build @@ -0,0 +1,41 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +with Files("**"): + BUG_COMPONENT = ("Toolkit", "General") + +DIRS += ["build"] + +XPIDL_SOURCES += [ + "nsIWebBrowser.idl", + "nsIWebBrowserChrome.idl", + "nsIWebBrowserChromeFocus.idl", +] + +XPIDL_SOURCES += [ + "nsIWebBrowserPrint.idl", +] + +XPIDL_MODULE = "webBrowser_core" + +UNIFIED_SOURCES += [ + "nsWebBrowser.cpp", + "nsWebBrowserContentPolicy.cpp", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +FINAL_LIBRARY = "xul" +LOCAL_INCLUDES += [ + "/docshell/base", + "/dom/base", + "/layout/style", +] + +EXPORTS += [ + "nsEmbedCID.h", + "nsWebBrowser.h", +] diff --git a/toolkit/components/browser/nsEmbedCID.h b/toolkit/components/browser/nsEmbedCID.h new file mode 100644 index 0000000000..126bb43b0a --- /dev/null +++ b/toolkit/components/browser/nsEmbedCID.h @@ -0,0 +1,44 @@ +/* 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/. */ + +#ifndef NSEMBEDCID_H +#define NSEMBEDCID_H + +/** + * @file + * @brief List of, and documentation for, frozen Gecko embedding contracts. + */ + +/** + * Web Browser ContractID + * Creating an instance of this ContractID (via createInstanceByContractID) + * is the basic way to instantiate a Gecko browser. + * + * This contract implements the following interfaces: + * nsIWebBrowser + * nsIWebBrowserSetup + * nsIInterfaceRequestor + * + * @note This contract does not guarantee implementation of any other + * interfaces and does not guarantee ability to get any particular + * interfaces via the nsIInterfaceRequestor implementation. + */ +#define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1" + +/** + * Prompt Service ContractID + * The prompt service (which can be gotten by calling getServiceByContractID + * on this ContractID) is the way to pose various prompts, alerts, + * and confirmation dialogs to the user. + * + * This contract implements the following interfaces: + * nsIPromptService + * + * Embedders may override this ContractID with their own implementation if they + * want more control over the way prompts, alerts, and confirmation dialogs are + * presented to the user. + */ +#define NS_PROMPTSERVICE_CONTRACTID "@mozilla.org/prompter;1" + +#endif // NSEMBEDCID_H diff --git a/toolkit/components/browser/nsIPrintPreviewNavigation.idl b/toolkit/components/browser/nsIPrintPreviewNavigation.idl new file mode 100644 index 0000000000..2a7676265d --- /dev/null +++ b/toolkit/components/browser/nsIPrintPreviewNavigation.idl @@ -0,0 +1,52 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "nsISupports.idl" + + +/** + * The nsIPrintPreviewNavigation + */ +[scriptable, uuid(8148E3F1-2E8B-11d5-A86C-00105A183419)] +interface nsIPrintPreviewNavigation : nsISupports +{ + + readonly attribute long pageCount; + + + /** + * Preview the next Page + * + * Return - PR_TRUE if success + */ + boolean nextPage(); + + /** + * Preview the previous Page + * + * Return - PR_TRUE if success + */ + boolean previousPage(); + + /** + * Go to a page to preview + * + * aPageNumber - Page to go preview + * Return - PR_TRUE if success + */ + boolean goToPage(unsigned long aPageNumber); + + + /** + * Skip pages + * + * aNumPages - number of pages to skip including the current page. Neg. goes back + * Return - true if success + */ + boolean skipPages(long aNumPages); + + +}; diff --git a/toolkit/components/browser/nsIWebBrowser.idl b/toolkit/components/browser/nsIWebBrowser.idl new file mode 100644 index 0000000000..a644dcd31e --- /dev/null +++ b/toolkit/components/browser/nsIWebBrowser.idl @@ -0,0 +1,81 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "nsISupports.idl" + +interface nsIInterfaceRequestor; +interface nsIWebBrowserChrome; +interface nsIURIContentListener; +interface mozIDOMWindowProxy; +interface nsIWeakReference; + +%{C++ +namespace mozilla { +class OriginAttributes; +} +%} + +[ref] native const_OriginAttributesRef(const mozilla::OriginAttributes); + +/** + * The nsIWebBrowser interface is implemented by web browser objects. + * Embedders use this interface during initialisation to associate + * the new web browser instance with the embedders chrome and + * to register any listeners. The interface may also be used at runtime + * to obtain the content DOM window and from that the rest of the DOM. + */ +[scriptable, builtinclass, uuid(4052b6da-4faa-4646-b3a1-7e16a01c2dc2)] +interface nsIWebBrowser : nsISupports +{ + /** + * The chrome object associated with the browser instance. The embedder + * must create one chrome object for each browser object + * that is instantiated. The embedder must associate the two by setting + * this property to point to the chrome object before creating the browser + * window via the browser's nsIBaseWindow interface. + * + * The chrome may optionally implement nsIInterfaceRequestor, + * nsIWebBrowserChromeFocus, + * nsIContextMenuListener and + * nsITooltipListener to receive additional notifications + * from the browser object. + * + * The chrome object may optionally implement + * nsIWebProgressListener to register a progress listener + * object. If the implementation does this, it must also implement + * nsIWeakReference. + * + * @note The implementation should not refcount the supplied chrome + * object; it should assume that a non nullptr value is + * always valid. The embedder must explicitly set this value back + * to nullptr if the chrome object is destroyed before the browser + * object. + * + * @see nsIBaseWindow + * @see nsIWebBrowserChrome + * @see nsIInterfaceRequestor + * @see nsIWebBrowserChromeFocus + * @see nsIContextMenuListener + * @see nsITooltipListener + * @see nsIWeakReference + * @see nsIWebProgressListener + */ + attribute nsIWebBrowserChrome containerWindow; + + /** + * The top-level DOM window. The embedder may walk the entire + * DOM starting from this value. + */ + readonly attribute mozIDOMWindowProxy contentDOMWindow; + + /** + * Set Origin Attributes on the nsIWebBrowser. + * The Origin Attributes will be passed to the docshell once it has been + * created + */ + [noscript, notxpcom, nostdcall, binaryname(SetOriginAttributes)] + void binarySetOriginAttributes(in const_OriginAttributesRef aOriginAttrs); +}; diff --git a/toolkit/components/browser/nsIWebBrowserChrome.idl b/toolkit/components/browser/nsIWebBrowserChrome.idl new file mode 100644 index 0000000000..54de3abab5 --- /dev/null +++ b/toolkit/components/browser/nsIWebBrowserChrome.idl @@ -0,0 +1,142 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "nsISupports.idl" +#include "nsIBaseWindow.idl" + +interface nsIWebBrowser; +interface nsIDocShellTreeItem; + +/** + * nsIWebBrowserChrome corresponds to the top-level, outermost window + * containing an embedded Gecko web browser. + */ + +[scriptable, uuid(E8C414C4-DC38-4BA3-AB4E-EC4CBBE22907)] +interface nsIWebBrowserChrome : nsISupports +{ + /** + * Called when the link hover status is being changed. + * @param status status string. empty string is an acceptable value + * meaning no link is hovered. + */ + void setLinkStatus(in AString status); + + /** + * Definitions for the chrome flags + */ + const unsigned long CHROME_DEFAULT = 0x00000001; + const unsigned long CHROME_WINDOW_BORDERS = 0x00000002; + const unsigned long CHROME_WINDOW_CLOSE = 0x00000004; + const unsigned long CHROME_WINDOW_RESIZE = 0x00000008; + const unsigned long CHROME_MENUBAR = 0x00000010; + const unsigned long CHROME_TOOLBAR = 0x00000020; + const unsigned long CHROME_LOCATIONBAR = 0x00000040; + const unsigned long CHROME_STATUSBAR = 0x00000080; + const unsigned long CHROME_PERSONAL_TOOLBAR = 0x00000100; + const unsigned long CHROME_SCROLLBARS = 0x00000200; + const unsigned long CHROME_TITLEBAR = 0x00000400; + const unsigned long CHROME_EXTRA = 0x00000800; + + // createBrowserWindow specific flags + const unsigned long CHROME_WITH_SIZE = 0x00001000; + const unsigned long CHROME_WITH_POSITION = 0x00002000; + + // special cases + const unsigned long CHROME_WINDOW_MIN = 0x00004000; + const unsigned long CHROME_WINDOW_POPUP = 0x00008000; + + // whether to open a new private window. CHROME_NON_PRIVATE_WINDOW + // forces the opened window to be non-private, and overrides + // CHROME_PRIVATE_WINDOW if it's set. CHROME_PRIVATE_WINDOW + // forces the opened window to be private. If neither of these + // flags are specified, the opened window will inherit the privacy + // status of its opener. If there is no opener window, the new + // window will be non-private. + // + // CHROME_PRIVATE_LIFETIME causes the docshell to affect private-browsing + // session lifetime. This flag is currently respected only for remote + // docshells. + const unsigned long CHROME_PRIVATE_WINDOW = 0x00010000; + const unsigned long CHROME_NON_PRIVATE_WINDOW = 0x00020000; + const unsigned long CHROME_PRIVATE_LIFETIME = 0x00040000; + const unsigned long CHROME_ALWAYS_ON_TOP = 0x00080000; + + // Whether this window should use remote (out-of-process) tabs. + const unsigned long CHROME_REMOTE_WINDOW = 0x00100000; + + // Whether this window should use out-of-process cross-origin subframes. + const unsigned long CHROME_FISSION_WINDOW = 0x00200000; + + // Prevents new window animations on MacOS and Windows. Currently + // ignored for Linux. + const unsigned long CHROME_SUPPRESS_ANIMATION = 0x01000000; + + const unsigned long CHROME_WINDOW_RAISED = 0x02000000; + const unsigned long CHROME_WINDOW_LOWERED = 0x04000000; + const unsigned long CHROME_CENTER_SCREEN = 0x08000000; + + // Make the new window dependent on the parent. This flag is only + // meaningful if CHROME_OPENAS_CHROME is set; content windows should not be + // dependent. + const unsigned long CHROME_DEPENDENT = 0x10000000; + + // Note: The modal style bit just affects the way the window looks and does + // mean it's actually modal. + const unsigned long CHROME_MODAL = 0x20000000; + const unsigned long CHROME_OPENAS_DIALOG = 0x40000000; + const unsigned long CHROME_OPENAS_CHROME = 0x80000000; + + const unsigned long CHROME_ALL = 0x00000ffe; + + const unsigned long CHROME_MINIMAL_POPUP = + CHROME_WINDOW_BORDERS | CHROME_WINDOW_CLOSE | CHROME_WINDOW_RESIZE | + CHROME_LOCATIONBAR | CHROME_STATUSBAR | CHROME_SCROLLBARS | + CHROME_TITLEBAR | CHROME_WINDOW_MIN; + + /** + * The chrome flags for this browser chrome. The implementation should + * reflect the value of this attribute by hiding or showing its chrome + * appropriately. + */ + attribute unsigned long chromeFlags; + + /** + * Shows the window as a modal window. + */ + void showAsModal(); + + /** + * Is the window modal (that is, currently executing a modal loop)? + * @return true if it's a modal window + */ + boolean isWindowModal(); + + /** + * Allows to request the change of individual dimensions of a window + * without specifying all dimensions. + * + * Gets called as fallback when no nsIBaseWindow is available. + * + * @see nsIBaseWindow + */ + void setDimensions(in DimensionRequest aRequest); + + /** + * Gets the dimensions of the window. The caller may pass + * nullptr for any value it is uninterested in receiving. + * + * Gets called as fallback when no nsIBaseWindow is available. + * + * @see nsIBaseWindow + */ + void getDimensions(in DimensionKind aDimensionKind, out long aX, out long aY, out long aCX, out long aCY); + + /** + * Blur the window. This should unfocus the window and send an onblur event. + */ + void blur(); +}; diff --git a/toolkit/components/browser/nsIWebBrowserChromeFocus.idl b/toolkit/components/browser/nsIWebBrowserChromeFocus.idl new file mode 100644 index 0000000000..ee24155b51 --- /dev/null +++ b/toolkit/components/browser/nsIWebBrowserChromeFocus.idl @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 0 -*- + * + * 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/. */ + +#include "nsISupports.idl" + +/** + * The nsIWebBrowserChromeFocus is implemented by the same object as the + * nsIEmbeddingSiteWindow. It represents the focus up-calls from mozilla + * to the embedding chrome. See mozilla bug #70224 for gratuitous info. + */ + +[scriptable, uuid(947B2EE6-51ED-4C2B-9F45-426C27CA84C6)] +interface nsIWebBrowserChromeFocus : nsISupports +{ + /** + * Set the focus at the next focusable element in the chrome. If + * aForDocumentNavigation is true, this was a document navigation, so + * focus the parent window. + */ + + void focusNextElement(in bool aForDocumentNavigation); + + /** + * Set the focus at the previous focusable element in the chrome. + */ + + void focusPrevElement(in bool aForDocumentNavigation); + +}; diff --git a/toolkit/components/browser/nsIWebBrowserPrint.idl b/toolkit/components/browser/nsIWebBrowserPrint.idl new file mode 100644 index 0000000000..5a900b7b65 --- /dev/null +++ b/toolkit/components/browser/nsIWebBrowserPrint.idl @@ -0,0 +1,129 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "nsISupports.idl" + +%{C++ +#include + +namespace mozilla { +namespace dom { +class PrintPreviewResultInfo; +} // namespace dom +namespace layout { +class RemotePrintJobChild; +} // namespace layout +} // namespace mozilla +%} + +interface mozIDOMWindowProxy; +interface nsIPrintSettings; +interface nsIWebProgressListener; + +native PrintPreviewResolver(std::function&&); +[ptr] native RemotePrintJobChildPtr(mozilla::layout::RemotePrintJobChild); + +/** + * nsIWebBrowserPrint corresponds to the main interface + * for printing an embedded Gecko web browser window/document + */ +[scriptable, uuid(c9a934ed-fff1-4971-bfba-6c25ad70e1e6)] +interface nsIWebBrowserPrint : nsISupports +{ + /** + * PrintPreview Navigation Constants + * + * XXXdholbert Consider renaming these? Strictly speaking, these deal with + * *sheets* (which are roughly the same as pages in the default configuration + * of one page per sheet). Fix in bug 1669762. + */ + const short PRINTPREVIEW_GOTO_PAGENUM = 0; + const short PRINTPREVIEW_PREV_PAGE = 1; + const short PRINTPREVIEW_NEXT_PAGE = 2; + const short PRINTPREVIEW_HOME = 3; + const short PRINTPREVIEW_END = 4; + + /** + * Returns whether it is in Print mode + */ + readonly attribute boolean doingPrint; + + /** + * Returns whether it is in Print Preview mode + */ + readonly attribute boolean doingPrintPreview; + + /** + * This represents the "raw" total number of pages, where "raw" means that + * this value is *not amended* to account for reductions from pages-per-sheet + * or page ranges (unlike other APIs on this interface). + * + * So e.g. for a 20-page document, this attribute will be 20, regardless of + * whether the user has chosen a smaller page range, and regardless of + * whether the user is using pages-per-sheet to reduce the number of sheets. + */ + readonly attribute long rawNumPages; + + /** + * This returns the total number of pages for the Print Preview + * + * XXXdholbert Consider renaming this? Strictly speaking, this is the number + * of *sheets* (which is the same as the number of pages in the default + * configuration of one page per sheet). Fix in bug 1669762. + */ + readonly attribute long printPreviewNumPages; + + /** + * This returns the number of the page which is currently in the Print Preview viewport + * + * XXXdholbert Consider renaming this? (similar to printPreviewNumPages above) + * Strictly speaking, this is the number of the *sheet* which is currently in + * the print preview viewport. Fix in bug 1669762. + */ + readonly attribute long printPreviewCurrentPageNumber; + + /** + * Print the specified DOM window + * + * @param aThePrintSettings - Printer Settings for the print job, if aThePrintSettings is null + * then the global PS will be used. + * @param aWPListener - is updated during the print + * @return void + * + * @note To cancel, close the window of the document that is being printed. + */ + [noscript] void print(in nsIPrintSettings aThePrintSettings, + in RemotePrintJobChildPtr aRemotePrintJob, + in nsIWebProgressListener aWPListener); + + /** + * Print Preview the specified DOM window + * + * @param aThePrintSettings - Printer Settings for the print preview, if aThePrintSettings is null + * then the global PS will be used. + * @param aWPListener - is updated during the printpreview + * @return void + * + * @note To cancel, close the print preview document's window. + */ + [noscript] void printPreview(in nsIPrintSettings aThePrintSettings, + in nsIWebProgressListener aWPListener, + in PrintPreviewResolver aCallback); + + /** + * @param aNavType - navigation enum + * @param aPageNum - page num to navigate to when aNavType = ePrintPreviewGoToPageNum + * @return void + */ + void printPreviewScrollToPage(in short aNavType, in long aPageNum); + + /** + * This exists PrintPreview mode and returns browser window to galley mode + * @return void + */ + void exitPrintPreview(); + +}; diff --git a/toolkit/components/browser/nsWebBrowser.cpp b/toolkit/components/browser/nsWebBrowser.cpp new file mode 100644 index 0000000000..53ed9eb1a4 --- /dev/null +++ b/toolkit/components/browser/nsWebBrowser.cpp @@ -0,0 +1,1241 @@ +/* -*- 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 "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; + } + + widget::InitData widgetInit; + widgetInit.mClipChildren = true; + widgetInit.mWindowType = widget::WindowType::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::Create( + nsIWebBrowserChrome* aContainerWindow, nsIWidget* aParentWidget, + dom::BrowsingContext* aBrowsingContext, + dom::WindowGlobalChild* aInitialWindowChild) { + MOZ_ASSERT_IF(aInitialWindowChild, + aInitialWindowChild->BrowsingContext() == aBrowsingContext); + + RefPtr 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 docShellParentWidget = browser->EnsureWidget(); + if (NS_WARN_IF(!docShellParentWidget)) { + return nullptr; + } + + uint64_t outerWindowId = + aInitialWindowChild ? aInitialWindowChild->OuterWindowId() : 0; + + RefPtr 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 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 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 mDocShell->GetInterface(aIID, aSink); + } + + return NS_NOINTERFACE; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebBrowser +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetContainerWindow(nsIWebBrowserChrome** aTopWindow) { + NS_ENSURE_ARG_POINTER(aTopWindow); + + nsCOMPtr 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 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(this); + + nsCOMPtr 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(this); + + nsCOMPtr 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); + + RefPtr docShell = mDocShell; + return docShell->GoBack(aRequireUserInteraction, aUserActivation); +} + +NS_IMETHODIMP +nsWebBrowser::GoForward(bool aRequireUserInteraction, bool aUserActivation) { + NS_ENSURE_STATE(mDocShell); + + RefPtr docShell = mDocShell; + return docShell->GoForward(aRequireUserInteraction, aUserActivation); +} + +nsresult nsWebBrowser::LoadURI(nsIURI* aURI, + const dom::LoadURIOptions& aLoadURIOptions) { +#ifndef ANDROID + MOZ_ASSERT(aLoadURIOptions.mTriggeringPrincipal, + "nsWebBrowser::LoadURI - Need a valid triggeringPrincipal"); +#endif + NS_ENSURE_STATE(mDocShell); + + RefPtr docShell = mDocShell; + return docShell->LoadURI(aURI, aLoadURIOptions); +} + +NS_IMETHODIMP +nsWebBrowser::LoadURIFromScript(nsIURI* aURI, + JS::Handle 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); +} + +nsresult nsWebBrowser::FixupAndLoadURIString( + const nsAString& aURI, const dom::LoadURIOptions& aLoadURIOptions) { +#ifndef ANDROID + MOZ_ASSERT( + aLoadURIOptions.mTriggeringPrincipal, + "nsWebBrowser::FixupAndLoadURIString - Need a valid triggeringPrincipal"); +#endif + NS_ENSURE_STATE(mDocShell); + + RefPtr docShell = mDocShell; + return docShell->FixupAndLoadURIString(aURI, aLoadURIOptions); +} + +NS_IMETHODIMP +nsWebBrowser::FixupAndLoadURIStringFromScript( + const nsAString& aURI, JS::Handle aLoadURIOptions, + JSContext* aCx) { + // generate dictionary for loadURIOptions and forward call + dom::LoadURIOptions loadURIOptions; + if (!loadURIOptions.Init(aCx, aLoadURIOptions)) { + return NS_ERROR_INVALID_ARG; + } + return FixupAndLoadURIString(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); + + RefPtr docShell = mDocShell; + return docShell->Reload(aReloadFlags); +} + +NS_IMETHODIMP +nsWebBrowser::GotoIndex(int32_t aIndex, bool aUserActivation) { + NS_ENSURE_STATE(mDocShell); + + RefPtr docShell = mDocShell; + return docShell->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, 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->SaveURI(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 doc; + if (aDocumentish) { + doc = aDocumentish; + } else { + RefPtr domDoc; + GetDocument(getter_AddRefs(domDoc)); + doc = already_AddRefed(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 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; + } + + // Can directly return this as it is the + // same interface, thus same returns. + return mDocShell->GetPositionAndSize(aX, aY, aCX, aCY); +} + +NS_IMETHODIMP +nsWebBrowser::SetDimensions(DimensionRequest&& aRequest) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsWebBrowser::GetDimensions(DimensionKind aDimensionKind, int32_t* aX, + int32_t* aY, int32_t* aCX, int32_t* aCY) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +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 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 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 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 fm = nsFocusManager::GetFocusManager()) { + if (nsCOMPtr window = GetWindow()) { + fm->WindowRaised(window, aActionId); + } + } +} + +void nsWebBrowser::FocusDeactivate(uint64_t aActionId) { + if (RefPtr fm = nsFocusManager::GetFocusManager()) { + if (nsCOMPtr window = GetWindow()) { + fm->WindowLowered(window, aActionId); + } + } +} + +void nsWebBrowser::SetWillChangeProcess() { + mWillChangeProcess = true; + if (mDocShell) { + nsDocShell::Cast(mDocShell)->SetWillChangeProcess(); + } +} + +void nsWebBrowser::WidgetListenerDelegate::WindowActivated() { + RefPtr holder = mWebBrowser; + holder->WindowActivated(); +} + +void nsWebBrowser::WidgetListenerDelegate::WindowDeactivated() { + RefPtr holder = mWebBrowser; + holder->WindowDeactivated(); +} + +bool nsWebBrowser::WidgetListenerDelegate::PaintWindow( + nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) { + RefPtr holder = mWebBrowser; + return holder->PaintWindow(aWidget, aRegion); +} diff --git a/toolkit/components/browser/nsWebBrowser.h b/toolkit/components/browser/nsWebBrowser.h new file mode 100644 index 0000000000..f2cbaeb938 --- /dev/null +++ b/toolkit/components/browser/nsWebBrowser.h @@ -0,0 +1,164 @@ +/* -*- 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/. */ + +#ifndef nsWebBrowser_h__ +#define nsWebBrowser_h__ + +// Local Includes +#include "nsDocShellTreeOwner.h" + +// Core Includes +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" + +// Interfaces needed +#include "nsIBaseWindow.h" +#include "nsIDocShell.h" +#include "nsIDocShellTreeItem.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIWidget.h" +#include "nsIWebProgress.h" +#include "nsIWebBrowser.h" +#include "nsIWebNavigation.h" +#include "nsIWebBrowserPersist.h" +#include "nsIWindowWatcher.h" +#include "nsIPrintSettings.h" +#include "nsIWidgetListener.h" + +#include "mozilla/BasePrincipal.h" +#include "nsTArray.h" +#include "nsIWeakReferenceUtils.h" + +class nsWebBrowserInitInfo { + public: + // nsIBaseWindow Stuff + int32_t x; + int32_t y; + int32_t cx; + int32_t cy; + bool visible; + nsString name; +}; + +// {cda5863a-aa9c-411e-be49-ea0d525ab4b5} - +#define NS_WEBBROWSER_CID \ + { \ + 0xcda5863a, 0xaa9c, 0x411e, { \ + 0xbe, 0x49, 0xea, 0x0d, 0x52, 0x5a, 0xb4, 0xb5 \ + } \ + } + +class mozIDOMWindowProxy; +class nsDocShell; + +namespace mozilla { +namespace dom { +class WindowGlobalChild; +} // namespace dom +} // namespace mozilla + +class nsWebBrowser final : public nsIWebBrowser, + public nsIWebNavigation, + public nsIDocShellTreeItem, + public nsIBaseWindow, + public nsIInterfaceRequestor, + public nsIWebBrowserPersist, + public nsIWebProgressListener, + public nsSupportsWeakReference { + friend class nsDocShellTreeOwner; + + public: + // The implementation of non-refcounted nsIWidgetListener, which would hold a + // strong reference on stack before calling nsWebBrowser's + // MOZ_CAN_RUN_SCRIPT methods. + class WidgetListenerDelegate : public nsIWidgetListener { + public: + explicit WidgetListenerDelegate(nsWebBrowser* aWebBrowser) + : mWebBrowser(aWebBrowser) {} + MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void WindowActivated() override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void WindowDeactivated() override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual bool PaintWindow( + nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) override; + + private: + // The lifetime of WidgetListenerDelegate is bound to nsWebBrowser so we + // just use raw pointer here. + nsWebBrowser* mWebBrowser; + }; + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsWebBrowser, nsIWebBrowser) + + NS_DECL_NSIBASEWINDOW + NS_DECL_NSIDOCSHELLTREEITEM + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSIWEBBROWSER + NS_DECL_NSIWEBNAVIGATION + NS_DECL_NSIWEBBROWSERPERSIST + NS_DECL_NSICANCELABLE + NS_DECL_NSIWEBPROGRESSLISTENER + + void SetAllowDNSPrefetch(bool aAllowPrefetch); + // TODO: Convert FocusDeactivate() to MOZ_CAN_RUN_SCRIPT + MOZ_CAN_RUN_SCRIPT_BOUNDARY void FocusActivate(uint64_t aActionId); + // TODO: Convert FocusDeactivate() to MOZ_CAN_RUN_SCRIPT + MOZ_CAN_RUN_SCRIPT_BOUNDARY void FocusDeactivate(uint64_t aActionId); + void SetWillChangeProcess(); + + static already_AddRefed Create( + nsIWebBrowserChrome* aContainerWindow, nsIWidget* aParentWidget, + mozilla::dom::BrowsingContext* aBrowsingContext, + mozilla::dom::WindowGlobalChild* aInitialWindowChild); + + protected: + virtual ~nsWebBrowser(); + void InternalDestroy(); + + void SetDocShell(nsDocShell* aDocShell); + void EnsureDocShellTreeOwner(); + + nsIWidget* EnsureWidget(); + + // nsIWidgetListener methods for WidgetListenerDelegate. + MOZ_CAN_RUN_SCRIPT void WindowActivated(); + MOZ_CAN_RUN_SCRIPT void WindowDeactivated(); + MOZ_CAN_RUN_SCRIPT bool PaintWindow(nsIWidget* aWidget, + mozilla::LayoutDeviceIntRegion aRegion); + + explicit nsWebBrowser(int aItemType); + + protected: + RefPtr mDocShellTreeOwner; + RefPtr mDocShell; + mozilla::OriginAttributes mOriginAttributes; + + nsCOMPtr mInternalWidget; + nsCOMPtr mWWatch; + const uint32_t mContentType; + bool mShouldEnableHistory; + bool mWillChangeProcess; + nativeWindow mParentNativeWindow; + nsIWebProgressListener* mProgressListener; + + nsCOMPtr mPrintSettings; + + WidgetListenerDelegate mWidgetListenerDelegate; + + // cached background color + nscolor mBackgroundColor; + + // persistence object + nsCOMPtr mPersist; + uint32_t mPersistCurrentState; + nsresult mPersistResult; + uint32_t mPersistFlags; + + // Weak Reference interfaces... + nsIWidget* mParentWidget; +}; + +#endif /* nsWebBrowser_h__ */ diff --git a/toolkit/components/browser/nsWebBrowserContentPolicy.cpp b/toolkit/components/browser/nsWebBrowserContentPolicy.cpp new file mode 100644 index 0000000000..fcb8af485c --- /dev/null +++ b/toolkit/components/browser/nsWebBrowserContentPolicy.cpp @@ -0,0 +1,87 @@ +/* -*- 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/. */ + +#include "nsWebBrowserContentPolicy.h" +#include "nsIDocShell.h" +#include "nsCOMPtr.h" +#include "nsContentPolicyUtils.h" +#include "nsNetUtil.h" + +nsWebBrowserContentPolicy::nsWebBrowserContentPolicy() = default; + +nsWebBrowserContentPolicy::~nsWebBrowserContentPolicy() = default; + +NS_IMPL_ISUPPORTS(nsWebBrowserContentPolicy, nsIContentPolicy) + +NS_IMETHODIMP +nsWebBrowserContentPolicy::ShouldLoad(nsIURI* aContentLocation, + nsILoadInfo* aLoadInfo, + const nsACString& aMimeGuess, + int16_t* aShouldLoad) { + MOZ_ASSERT(aShouldLoad, "Null out param"); + + ExtContentPolicyType contentType = aLoadInfo->GetExternalContentPolicyType(); + + *aShouldLoad = nsIContentPolicy::ACCEPT; + + nsCOMPtr context = aLoadInfo->GetLoadingContext(); + nsIDocShell* shell = NS_CP_GetDocShellFromContext(context); + /* We're going to dereference shell, so make sure it isn't null */ + if (!shell) { + return NS_OK; + } + + nsresult rv; + bool allowed = true; + + switch (contentType) { + case ExtContentPolicy::TYPE_SUBDOCUMENT: + rv = shell->GetAllowSubframes(&allowed); + break; + case ExtContentPolicy::TYPE_IMAGE: + case ExtContentPolicy::TYPE_IMAGESET: + rv = shell->GetAllowImages(&allowed); + break; + default: + return NS_OK; + } + + if (NS_SUCCEEDED(rv) && !allowed) { + NS_SetRequestBlockingReason( + aLoadInfo, nsILoadInfo::BLOCKING_REASON_CONTENT_POLICY_WEB_BROWSER); + *aShouldLoad = nsIContentPolicy::REJECT_TYPE; + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowserContentPolicy::ShouldProcess(nsIURI* aContentLocation, + nsILoadInfo* aLoadInfo, + const nsACString& aMimeGuess, + int16_t* aShouldProcess) { + MOZ_ASSERT(aShouldProcess, "Null out param"); + + ExtContentPolicyType contentType = aLoadInfo->GetExternalContentPolicyType(); + + *aShouldProcess = nsIContentPolicy::ACCEPT; + + // Object tags will always open channels with TYPE_OBJECT, but may end up + // loading with TYPE_IMAGE or TYPE_DOCUMENT as their final type, so we block + // actual-plugins at the process stage + if (contentType != ExtContentPolicy::TYPE_OBJECT) { + return NS_OK; + } + + nsCOMPtr context = aLoadInfo->GetLoadingContext(); + nsIDocShell* shell = NS_CP_GetDocShellFromContext(context); + if (shell && (!shell->PluginsAllowedInCurrentDoc())) { + NS_SetRequestBlockingReason( + aLoadInfo, nsILoadInfo::BLOCKING_REASON_CONTENT_POLICY_WEB_BROWSER); + *aShouldProcess = nsIContentPolicy::REJECT_TYPE; + } + + return NS_OK; +} diff --git a/toolkit/components/browser/nsWebBrowserContentPolicy.h b/toolkit/components/browser/nsWebBrowserContentPolicy.h new file mode 100644 index 0000000000..7b778baf5a --- /dev/null +++ b/toolkit/components/browser/nsWebBrowserContentPolicy.h @@ -0,0 +1,29 @@ +/* -*- 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/. */ + +#include "nsIContentPolicy.h" + +/* f66bc334-1dd1-11b2-bab2-90e04fe15c19 */ +#define NS_WEBBROWSERCONTENTPOLICY_CID \ + { \ + 0xf66bc334, 0x1dd1, 0x11b2, { \ + 0xba, 0xb2, 0x90, 0xe0, 0x4f, 0xe1, 0x5c, 0x19 \ + } \ + } + +#define NS_WEBBROWSERCONTENTPOLICY_CONTRACTID \ + "@mozilla.org/embedding/browser/content-policy;1" + +class nsWebBrowserContentPolicy : public nsIContentPolicy { + protected: + virtual ~nsWebBrowserContentPolicy(); + + public: + nsWebBrowserContentPolicy(); + + NS_DECL_ISUPPORTS + NS_DECL_NSICONTENTPOLICY +}; -- cgit v1.2.3