diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /embedding/browser | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'embedding/browser')
34 files changed, 6575 insertions, 0 deletions
diff --git a/embedding/browser/build/moz.build b/embedding/browser/build/moz.build new file mode 100644 index 000000000..cdd0f5a76 --- /dev/null +++ b/embedding/browser/build/moz.build @@ -0,0 +1,14 @@ +# -*- 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/. + +SOURCES += [ + 'nsWebBrowserModule.cpp', +] + +FINAL_LIBRARY = 'xul' +LOCAL_INCLUDES += [ + '..', +] diff --git a/embedding/browser/build/nsWebBrowserModule.cpp b/embedding/browser/build/nsWebBrowserModule.cpp new file mode 100644 index 000000000..a061a2b43 --- /dev/null +++ b/embedding/browser/build/nsWebBrowserModule.cpp @@ -0,0 +1,53 @@ +/* -*- 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 "mozilla/ModuleUtils.h" +#include "nsIServiceManager.h" +#include "nsXPIDLString.h" + +#include "nsEmbedCID.h" + +#include "nsWebBrowser.h" +#include "nsCommandHandler.h" +#include "nsWebBrowserContentPolicy.h" + +// Factory Constructors + +NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebBrowser) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebBrowserContentPolicy) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsCommandHandler) + +NS_DEFINE_NAMED_CID(NS_WEBBROWSER_CID); +NS_DEFINE_NAMED_CID(NS_COMMANDHANDLER_CID); +NS_DEFINE_NAMED_CID(NS_WEBBROWSERCONTENTPOLICY_CID); + +static const mozilla::Module::CIDEntry kWebBrowserCIDs[] = { + { &kNS_WEBBROWSER_CID, false, nullptr, nsWebBrowserConstructor }, + { &kNS_COMMANDHANDLER_CID, false, nullptr, nsCommandHandlerConstructor }, + { &kNS_WEBBROWSERCONTENTPOLICY_CID, false, nullptr, nsWebBrowserContentPolicyConstructor }, + { nullptr } +}; + +static const mozilla::Module::ContractIDEntry kWebBrowserContracts[] = { + { NS_WEBBROWSER_CONTRACTID, &kNS_WEBBROWSER_CID }, + { NS_COMMANDHANDLER_CONTRACTID, &kNS_COMMANDHANDLER_CID }, + { NS_WEBBROWSERCONTENTPOLICY_CONTRACTID, &kNS_WEBBROWSERCONTENTPOLICY_CID }, + { nullptr } +}; + +static const mozilla::Module::CategoryEntry kWebBrowserCategories[] = { + { "content-policy", NS_WEBBROWSERCONTENTPOLICY_CONTRACTID, NS_WEBBROWSERCONTENTPOLICY_CONTRACTID }, + { nullptr } +}; + +static const mozilla::Module kWebBrowserModule = { + mozilla::Module::kVersion, + kWebBrowserCIDs, + kWebBrowserContracts, + kWebBrowserCategories +}; + +NSMODULE_DEFN(Browser_Embedding_Module) = &kWebBrowserModule; diff --git a/embedding/browser/moz.build b/embedding/browser/moz.build new file mode 100644 index 000000000..179a6b6c8 --- /dev/null +++ b/embedding/browser/moz.build @@ -0,0 +1,57 @@ +# -*- 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/. + +DIRS += ['build'] + +XPIDL_SOURCES += [ + 'nsCWebBrowser.idl', + 'nsICommandHandler.idl', + 'nsIContextMenuListener.idl', + 'nsIContextMenuListener2.idl', + 'nsIEmbeddingSiteWindow.idl', + 'nsITooltipListener.idl', + 'nsITooltipTextProvider.idl', + 'nsIWebBrowser.idl', + 'nsIWebBrowserChrome.idl', + 'nsIWebBrowserChrome2.idl', + 'nsIWebBrowserChrome3.idl', + 'nsIWebBrowserChromeFocus.idl', + 'nsIWebBrowserFocus.idl', + 'nsIWebBrowserSetup.idl', + 'nsIWebBrowserStream.idl', +] + +if CONFIG['NS_PRINTING']: + XPIDL_SOURCES += [ + 'nsIPrintingPromptService.idl', + 'nsIWebBrowserPrint.idl', + ] + +XPIDL_MODULE = 'webBrowser_core' + +EXPORTS += [ + 'nsCTooltipTextProvider.h', +] + +UNIFIED_SOURCES += [ + 'nsCommandHandler.cpp', + 'nsContextMenuInfo.cpp', + 'nsDocShellTreeOwner.cpp', + 'nsEmbedStream.cpp', + 'nsWebBrowser.cpp', + 'nsWebBrowserContentPolicy.cpp', +] + +FINAL_LIBRARY = 'xul' +LOCAL_INCLUDES += [ + '/docshell/base', + '/dom/base', + '/dom/svg', + '/layout/style', +] + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wno-error=shadow'] diff --git a/embedding/browser/nsCTooltipTextProvider.h b/embedding/browser/nsCTooltipTextProvider.h new file mode 100644 index 000000000..95fb00432 --- /dev/null +++ b/embedding/browser/nsCTooltipTextProvider.h @@ -0,0 +1,17 @@ +/* -*- 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 NSCTOOLTIPTEXTPROVIDER_H +#define NSCTOOLTIPTEXTPROVIDER_H + +#include "nsITooltipTextProvider.h" + +#define NS_TOOLTIPTEXTPROVIDER_CONTRACTID \ + "@mozilla.org/embedcomp/tooltiptextprovider;1" +#define NS_DEFAULTTOOLTIPTEXTPROVIDER_CONTRACTID \ + "@mozilla.org/embedcomp/default-tooltiptextprovider;1" + +#endif diff --git a/embedding/browser/nsCWebBrowser.idl b/embedding/browser/nsCWebBrowser.idl new file mode 100644 index 000000000..21927f7c7 --- /dev/null +++ b/embedding/browser/nsCWebBrowser.idl @@ -0,0 +1,34 @@ +/* -*- 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 "nsIWebBrowser.idl" +#include "nsIBaseWindow.idl" +#include "nsIScrollable.idl" +#include "nsITextScroll.idl" + +/* +nsCWebBrowser implements: +------------------------- +nsIWebBrowser +nsIDocShellTreeItem +nsIWebNavigation +nsIWebProgress +nsIBaseWindow +nsIScrollable +nsITextScroll +nsIInterfaceRequestor + + +Outwardly communicates with: +---------------------------- +nsIWebBrowserChrome +nsIBaseWindow +nsIInterfaceRequestor +*/ + +%{ C++ +#include "nsEmbedCID.h" +%} diff --git a/embedding/browser/nsCommandHandler.cpp b/embedding/browser/nsCommandHandler.cpp new file mode 100644 index 000000000..1e41e265a --- /dev/null +++ b/embedding/browser/nsCommandHandler.cpp @@ -0,0 +1,139 @@ +/* -*- 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 "nsCommandHandler.h" +#include "nsWebBrowser.h" +#include "nsDocShellTreeOwner.h" + +#include "nsMemory.h" +#include "nsPIDOMWindow.h" + +nsCommandHandler::nsCommandHandler() + : mWindow(nullptr) +{ +} + +nsCommandHandler::~nsCommandHandler() +{ +} + +nsresult +nsCommandHandler::GetCommandHandler(nsICommandHandler** aCommandHandler) +{ + NS_ENSURE_ARG_POINTER(aCommandHandler); + + *aCommandHandler = nullptr; + if (!mWindow) { + return NS_ERROR_FAILURE; + } + + // Get the document tree owner + + nsCOMPtr<nsIDocShellTreeItem> docShellAsTreeItem = + do_QueryInterface(mWindow->GetDocShell()); + nsIDocShellTreeOwner* treeOwner = nullptr; + docShellAsTreeItem->GetTreeOwner(&treeOwner); + + // Make sure the tree owner is an an nsDocShellTreeOwner object + // by QI'ing for a hidden interface. If it doesn't have the interface + // then it's not safe to do the casting. + + nsCOMPtr<nsICDocShellTreeOwner> realTreeOwner(do_QueryInterface(treeOwner)); + if (realTreeOwner) { + nsDocShellTreeOwner* tree = static_cast<nsDocShellTreeOwner*>(treeOwner); + if (tree->mTreeOwner) { + nsresult rv; + rv = tree->mTreeOwner->QueryInterface(NS_GET_IID(nsICommandHandler), + (void**)aCommandHandler); + NS_RELEASE(treeOwner); + return rv; + } + + NS_RELEASE(treeOwner); + } + + *aCommandHandler = nullptr; + + return NS_OK; +} + +NS_IMPL_ADDREF(nsCommandHandler) +NS_IMPL_RELEASE(nsCommandHandler) + +NS_INTERFACE_MAP_BEGIN(nsCommandHandler) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICommandHandler) + NS_INTERFACE_MAP_ENTRY(nsICommandHandlerInit) + NS_INTERFACE_MAP_ENTRY(nsICommandHandler) +NS_INTERFACE_MAP_END + +/////////////////////////////////////////////////////////////////////////////// +// nsICommandHandlerInit implementation + +NS_IMETHODIMP +nsCommandHandler::GetWindow(mozIDOMWindowProxy** aWindow) +{ + *aWindow = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +nsCommandHandler::SetWindow(mozIDOMWindowProxy* aWindow) +{ + if (!aWindow) { + return NS_ERROR_FAILURE; + } + mWindow = nsPIDOMWindowOuter::From(aWindow); + return NS_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +// nsICommandHandler implementation + +NS_IMETHODIMP +nsCommandHandler::Exec(const char* aCommand, const char* aStatus, + char** aResult) +{ + NS_ENSURE_ARG_POINTER(aCommand); + NS_ENSURE_ARG_POINTER(aResult); + + nsCOMPtr<nsICommandHandler> commandHandler; + GetCommandHandler(getter_AddRefs(commandHandler)); + + // Call the client's command handler to deal with this command + if (commandHandler) { + *aResult = nullptr; + return commandHandler->Exec(aCommand, aStatus, aResult); + } + + // Return an empty string + const char szEmpty[] = ""; + *aResult = (char*)nsMemory::Clone(szEmpty, sizeof(szEmpty)); + + return NS_OK; +} + +NS_IMETHODIMP +nsCommandHandler::Query(const char* aCommand, const char* aStatus, + char** aResult) +{ + NS_ENSURE_ARG_POINTER(aCommand); + NS_ENSURE_ARG_POINTER(aResult); + + nsCOMPtr<nsICommandHandler> commandHandler; + GetCommandHandler(getter_AddRefs(commandHandler)); + + // Call the client's command handler to deal with this command + if (commandHandler) { + *aResult = nullptr; + return commandHandler->Query(aCommand, aStatus, aResult); + } + + // Return an empty string + const char szEmpty[] = ""; + *aResult = (char*)nsMemory::Clone(szEmpty, sizeof(szEmpty)); + + return NS_OK; +} diff --git a/embedding/browser/nsCommandHandler.h b/embedding/browser/nsCommandHandler.h new file mode 100644 index 000000000..3d229b9d6 --- /dev/null +++ b/embedding/browser/nsCommandHandler.h @@ -0,0 +1,35 @@ +/* -*- 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 NSCOMMANDHANDLER_H +#define NSCOMMANDHANDLER_H + +#include "nsISupports.h" +#include "nsICommandHandler.h" + +class nsPIDOMWindowOuter; + +class nsCommandHandler + : public nsICommandHandlerInit + , public nsICommandHandler +{ +public: + nsCommandHandler(); + + NS_DECL_ISUPPORTS + NS_DECL_NSICOMMANDHANDLERINIT + NS_DECL_NSICOMMANDHANDLER + +protected: + virtual ~nsCommandHandler(); + +private: + nsresult GetCommandHandler(nsICommandHandler** aCommandHandler); + + nsPIDOMWindowOuter* mWindow; +}; + +#endif diff --git a/embedding/browser/nsContextMenuInfo.cpp b/embedding/browser/nsContextMenuInfo.cpp new file mode 100644 index 000000000..5052dda65 --- /dev/null +++ b/embedding/browser/nsContextMenuInfo.cpp @@ -0,0 +1,326 @@ +/* -*- 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 "nsContextMenuInfo.h" + +#include "nsIImageLoadingContent.h" +#include "imgLoader.h" +#include "nsIDOMDocument.h" +#include "nsIDOMHTMLDocument.h" +#include "nsIDOMHTMLElement.h" +#include "nsIDOMHTMLHtmlElement.h" +#include "nsIDOMHTMLAnchorElement.h" +#include "nsIDOMHTMLImageElement.h" +#include "nsIDOMHTMLAreaElement.h" +#include "nsIDOMHTMLLinkElement.h" +#include "nsIDOMWindow.h" +#include "nsICSSDeclaration.h" +#include "nsIDOMCSSValue.h" +#include "nsIDOMCSSPrimitiveValue.h" +#include "nsNetUtil.h" +#include "nsUnicharUtils.h" +#include "nsIDocument.h" +#include "nsIPrincipal.h" +#include "nsIContentSecurityPolicy.h" +#include "nsIContentPolicy.h" +#include "imgRequestProxy.h" + +using mozilla::dom::Element; +using mozilla::ErrorResult; + +NS_IMPL_ISUPPORTS(nsContextMenuInfo, nsIContextMenuInfo) + +nsContextMenuInfo::nsContextMenuInfo() +{ +} + +nsContextMenuInfo::~nsContextMenuInfo() +{ +} + +NS_IMETHODIMP +nsContextMenuInfo::GetMouseEvent(nsIDOMEvent** aEvent) +{ + NS_ENSURE_ARG_POINTER(aEvent); + NS_IF_ADDREF(*aEvent = mMouseEvent); + return NS_OK; +} + +NS_IMETHODIMP +nsContextMenuInfo::GetTargetNode(nsIDOMNode** aNode) +{ + NS_ENSURE_ARG_POINTER(aNode); + NS_IF_ADDREF(*aNode = mDOMNode); + return NS_OK; +} + +NS_IMETHODIMP +nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef) +{ + NS_ENSURE_STATE(mAssociatedLink); + aHRef.Truncate(0); + + nsCOMPtr<nsIDOMElement> content(do_QueryInterface(mAssociatedLink)); + nsAutoString localName; + if (content) { + content->GetLocalName(localName); + } + + nsCOMPtr<nsIDOMElement> linkContent; + ToLowerCase(localName); + if (localName.EqualsLiteral("a") || + localName.EqualsLiteral("area") || + localName.EqualsLiteral("link")) { + bool hasAttr; + content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr); + if (hasAttr) { + linkContent = content; + nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent)); + if (anchor) { + anchor->GetHref(aHRef); + } else { + nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(linkContent)); + if (area) { + area->GetHref(aHRef); + } else { + nsCOMPtr<nsIDOMHTMLLinkElement> link(do_QueryInterface(linkContent)); + if (link) { + link->GetHref(aHRef); + } + } + } + } + } else { + nsCOMPtr<nsIDOMNode> curr; + mAssociatedLink->GetParentNode(getter_AddRefs(curr)); + while (curr) { + content = do_QueryInterface(curr); + if (!content) { + break; + } + content->GetLocalName(localName); + ToLowerCase(localName); + if (localName.EqualsLiteral("a")) { + bool hasAttr; + content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr); + if (hasAttr) { + linkContent = content; + nsCOMPtr<nsIDOMHTMLAnchorElement> anchor( + do_QueryInterface(linkContent)); + if (anchor) { + anchor->GetHref(aHRef); + } + } else { + linkContent = nullptr; // Links can't be nested. + } + break; + } + + nsCOMPtr<nsIDOMNode> temp = curr; + temp->GetParentNode(getter_AddRefs(curr)); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsContextMenuInfo::GetImageContainer(imgIContainer** aImageContainer) +{ + NS_ENSURE_ARG_POINTER(aImageContainer); + NS_ENSURE_STATE(mDOMNode); + + nsCOMPtr<imgIRequest> request; + GetImageRequest(mDOMNode, getter_AddRefs(request)); + if (request) { + return request->GetImage(aImageContainer); + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsContextMenuInfo::GetImageSrc(nsIURI** aURI) +{ + NS_ENSURE_ARG_POINTER(aURI); + NS_ENSURE_STATE(mDOMNode); + + nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mDOMNode)); + NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); + return content->GetCurrentURI(aURI); +} + +NS_IMETHODIMP +nsContextMenuInfo::GetBackgroundImageContainer(imgIContainer** aImageContainer) +{ + NS_ENSURE_ARG_POINTER(aImageContainer); + NS_ENSURE_STATE(mDOMNode); + + RefPtr<imgRequestProxy> request; + GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request)); + if (request) { + return request->GetImage(aImageContainer); + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsContextMenuInfo::GetBackgroundImageSrc(nsIURI** aURI) +{ + NS_ENSURE_ARG_POINTER(aURI); + NS_ENSURE_STATE(mDOMNode); + + RefPtr<imgRequestProxy> request; + GetBackgroundImageRequest(mDOMNode, getter_AddRefs(request)); + if (request) { + return request->GetURI(aURI); + } + + return NS_ERROR_FAILURE; +} + +nsresult +nsContextMenuInfo::GetImageRequest(nsIDOMNode* aDOMNode, imgIRequest** aRequest) +{ + NS_ENSURE_ARG(aDOMNode); + NS_ENSURE_ARG_POINTER(aRequest); + + // Get content + nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(aDOMNode)); + NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); + + return content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, aRequest); +} + +bool +nsContextMenuInfo::HasBackgroundImage(nsIDOMNode* aDOMNode) +{ + NS_ENSURE_TRUE(aDOMNode, false); + + RefPtr<imgRequestProxy> request; + GetBackgroundImageRequest(aDOMNode, getter_AddRefs(request)); + + return (request != nullptr); +} + +nsresult +nsContextMenuInfo::GetBackgroundImageRequest(nsIDOMNode* aDOMNode, + imgRequestProxy** aRequest) +{ + + NS_ENSURE_ARG(aDOMNode); + NS_ENSURE_ARG_POINTER(aRequest); + + nsCOMPtr<nsIDOMNode> domNode = aDOMNode; + + // special case for the <html> element: if it has no background-image + // we'll defer to <body> + nsCOMPtr<nsIDOMHTMLHtmlElement> htmlElement = do_QueryInterface(domNode); + if (htmlElement) { + nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(domNode); + nsAutoString nameSpace; + element->GetNamespaceURI(nameSpace); + if (nameSpace.IsEmpty()) { + nsresult rv = GetBackgroundImageRequestInternal(domNode, aRequest); + if (NS_SUCCEEDED(rv) && *aRequest) { + return NS_OK; + } + + // no background-image found + nsCOMPtr<nsIDOMDocument> document; + domNode->GetOwnerDocument(getter_AddRefs(document)); + nsCOMPtr<nsIDOMHTMLDocument> htmlDocument(do_QueryInterface(document)); + NS_ENSURE_TRUE(htmlDocument, NS_ERROR_FAILURE); + + nsCOMPtr<nsIDOMHTMLElement> body; + htmlDocument->GetBody(getter_AddRefs(body)); + domNode = do_QueryInterface(body); + NS_ENSURE_TRUE(domNode, NS_ERROR_FAILURE); + } + } + return GetBackgroundImageRequestInternal(domNode, aRequest); +} + +nsresult +nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode* aDOMNode, + imgRequestProxy** aRequest) +{ + NS_ENSURE_ARG_POINTER(aDOMNode); + + nsCOMPtr<nsIDOMNode> domNode = aDOMNode; + nsCOMPtr<nsIDOMNode> parentNode; + + nsCOMPtr<nsIDOMDocument> document; + domNode->GetOwnerDocument(getter_AddRefs(document)); + NS_ENSURE_TRUE(document, NS_ERROR_FAILURE); + + nsCOMPtr<mozIDOMWindowProxy> window; + document->GetDefaultView(getter_AddRefs(window)); + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); + + auto* piWindow = nsPIDOMWindowOuter::From(window); + nsPIDOMWindowInner* innerWindow = piWindow->GetCurrentInnerWindow(); + MOZ_ASSERT(innerWindow); + + nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue; + nsAutoString bgStringValue; + + nsCOMPtr<nsIDocument> doc(do_QueryInterface(document)); + nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr; + + while (true) { + nsCOMPtr<Element> domElement(do_QueryInterface(domNode)); + // bail for the parent node of the root element or null argument + if (!domElement) { + break; + } + + ErrorResult dummy; + nsCOMPtr<nsICSSDeclaration> computedStyle = + innerWindow->GetComputedStyle(*domElement, EmptyString(), dummy); + dummy.SuppressException(); + if (computedStyle) { + nsCOMPtr<nsIDOMCSSValue> cssValue; + computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-image"), + getter_AddRefs(cssValue)); + primitiveValue = do_QueryInterface(cssValue); + if (primitiveValue) { + primitiveValue->GetStringValue(bgStringValue); + if (!bgStringValue.EqualsLiteral("none")) { + nsCOMPtr<nsIURI> bgUri; + NS_NewURI(getter_AddRefs(bgUri), bgStringValue); + NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE); + + imgLoader* il = imgLoader::NormalLoader(); + NS_ENSURE_TRUE(il, NS_ERROR_FAILURE); + + return il->LoadImage(bgUri, nullptr, nullptr, + doc->GetReferrerPolicy(), principal, nullptr, + nullptr, nullptr, nullptr, nsIRequest::LOAD_NORMAL, + nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE, + EmptyString(), aRequest); + } + } + + // bail if we encounter non-transparent background-color + computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-color"), + getter_AddRefs(cssValue)); + primitiveValue = do_QueryInterface(cssValue); + if (primitiveValue) { + primitiveValue->GetStringValue(bgStringValue); + if (!bgStringValue.EqualsLiteral("transparent")) { + return NS_ERROR_FAILURE; + } + } + } + + domNode->GetParentNode(getter_AddRefs(parentNode)); + domNode = parentNode; + } + + return NS_ERROR_FAILURE; +} diff --git a/embedding/browser/nsContextMenuInfo.h b/embedding/browser/nsContextMenuInfo.h new file mode 100644 index 000000000..998045f97 --- /dev/null +++ b/embedding/browser/nsContextMenuInfo.h @@ -0,0 +1,54 @@ +/* -*- 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 nsContextMenuInfo_h__ +#define nsContextMenuInfo_h__ + +#include "nsCOMPtr.h" +#include "nsIContextMenuListener2.h" +#include "nsIDOMNode.h" +#include "nsIDOMEvent.h" +#include "imgIContainer.h" +#include "imgIRequest.h" + +class ChromeContextMenuListener; +class imgRequestProxy; + +// Helper class for implementors of nsIContextMenuListener2 +class nsContextMenuInfo : public nsIContextMenuInfo +{ + friend class ChromeContextMenuListener; + +public: + nsContextMenuInfo(); + + NS_DECL_ISUPPORTS + NS_DECL_NSICONTEXTMENUINFO + +private: + virtual ~nsContextMenuInfo(); + + void SetMouseEvent(nsIDOMEvent* aEvent) { mMouseEvent = aEvent; } + void SetDOMNode(nsIDOMNode* aNode) { mDOMNode = aNode; } + void SetAssociatedLink(nsIDOMNode* aLink) { mAssociatedLink = aLink; } + + nsresult GetImageRequest(nsIDOMNode* aDOMNode, imgIRequest** aRequest); + + bool HasBackgroundImage(nsIDOMNode* aDOMNode); + + nsresult GetBackgroundImageRequest(nsIDOMNode* aDOMNode, + imgRequestProxy** aRequest); + + nsresult GetBackgroundImageRequestInternal(nsIDOMNode* aDOMNode, + imgRequestProxy** aRequest); + +private: + nsCOMPtr<nsIDOMEvent> mMouseEvent; + nsCOMPtr<nsIDOMNode> mDOMNode; + nsCOMPtr<nsIDOMNode> mAssociatedLink; +}; + +#endif // nsContextMenuInfo_h__ diff --git a/embedding/browser/nsDocShellTreeOwner.cpp b/embedding/browser/nsDocShellTreeOwner.cpp new file mode 100644 index 000000000..73397cc8b --- /dev/null +++ b/embedding/browser/nsDocShellTreeOwner.cpp @@ -0,0 +1,1674 @@ +/* -*- 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 "nsDocShellTreeOwner.h" +#include "nsWebBrowser.h" + +// Helper Classes +#include "nsStyleCoord.h" +#include "nsSize.h" +#include "mozilla/ReflowInput.h" +#include "nsIServiceManager.h" +#include "nsComponentManagerUtils.h" +#include "nsXPIDLString.h" +#include "nsIAtom.h" +#include "nsReadableUtils.h" +#include "nsUnicharUtils.h" +#include "nsISimpleEnumerator.h" +#include "mozilla/LookAndFeel.h" + +// Interfaces needed to be included +#include "nsPresContext.h" +#include "nsIContextMenuListener.h" +#include "nsIContextMenuListener2.h" +#include "nsITooltipListener.h" +#include "nsIDOMNode.h" +#include "nsIDOMNodeList.h" +#include "nsIDOMDocument.h" +#include "nsIDOMDocumentType.h" +#include "nsIDOMElement.h" +#include "Link.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/SVGTitleElement.h" +#include "nsIDOMEvent.h" +#include "nsIDOMFileList.h" +#include "nsIDOMMouseEvent.h" +#include "nsIFormControl.h" +#include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLTextAreaElement.h" +#include "nsIDOMHTMLHtmlElement.h" +#include "nsIDOMHTMLAppletElement.h" +#include "nsIDOMHTMLObjectElement.h" +#include "nsIDOMHTMLEmbedElement.h" +#include "nsIDOMHTMLDocument.h" +#include "nsIImageLoadingContent.h" +#include "nsIWebNavigation.h" +#include "nsIDOMHTMLElement.h" +#include "nsIPresShell.h" +#include "nsIStringBundle.h" +#include "nsPIDOMWindow.h" +#include "nsPIWindowRoot.h" +#include "nsIDOMWindowCollection.h" +#include "nsIWindowWatcher.h" +#include "nsPIWindowWatcher.h" +#include "nsIPrompt.h" +#include "nsITabParent.h" +#include "nsITabChild.h" +#include "nsRect.h" +#include "nsIWebBrowserChromeFocus.h" +#include "nsIContent.h" +#include "imgIContainer.h" +#include "nsContextMenuInfo.h" +#include "nsPresContext.h" +#include "nsViewManager.h" +#include "nsView.h" +#include "nsIDOMDragEvent.h" +#include "nsIConstraintValidation.h" +#include "mozilla/Attributes.h" +#include "mozilla/EventListenerManager.h" +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() +#include "mozilla/dom/File.h" // for input type=file +#include "mozilla/dom/FileList.h" // for input type=file + +using namespace mozilla; +using namespace mozilla::dom; + +// A helper routine that navigates the tricky path from a |nsWebBrowser| to +// a |EventTarget| via the window root and chrome event handler. +static nsresult +GetDOMEventTarget(nsWebBrowser* aInBrowser, EventTarget** aTarget) +{ + if (!aInBrowser) { + return NS_ERROR_INVALID_POINTER; + } + + nsCOMPtr<mozIDOMWindowProxy> domWindow; + aInBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); + if (!domWindow) { + return NS_ERROR_FAILURE; + } + + auto* outerWindow = nsPIDOMWindowOuter::From(domWindow); + nsPIDOMWindowOuter* rootWindow = outerWindow->GetPrivateRoot(); + NS_ENSURE_TRUE(rootWindow, NS_ERROR_FAILURE); + nsCOMPtr<EventTarget> target = rootWindow->GetChromeEventHandler(); + NS_ENSURE_TRUE(target, NS_ERROR_FAILURE); + target.forget(aTarget); + + return NS_OK; +} + +nsDocShellTreeOwner::nsDocShellTreeOwner() + : mWebBrowser(nullptr) + , mTreeOwner(nullptr) + , mPrimaryContentShell(nullptr) + , mWebBrowserChrome(nullptr) + , mOwnerWin(nullptr) + , mOwnerRequestor(nullptr) +{ +} + +nsDocShellTreeOwner::~nsDocShellTreeOwner() +{ + RemoveChromeListeners(); +} + +NS_IMPL_ADDREF(nsDocShellTreeOwner) +NS_IMPL_RELEASE(nsDocShellTreeOwner) + +NS_INTERFACE_MAP_BEGIN(nsDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) + NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) + NS_INTERFACE_MAP_ENTRY(nsICDocShellTreeOwner) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) +NS_INTERFACE_MAP_END + +//***************************************************************************** +// nsDocShellTreeOwner::nsIInterfaceRequestor +//***************************************************************************** + +NS_IMETHODIMP +nsDocShellTreeOwner::GetInterface(const nsIID& aIID, void** aSink) +{ + NS_ENSURE_ARG_POINTER(aSink); + + if (NS_SUCCEEDED(QueryInterface(aIID, aSink))) { + return NS_OK; + } + + if (aIID.Equals(NS_GET_IID(nsIWebBrowserChromeFocus))) { + if (mWebBrowserChromeWeak != nullptr) { + return mWebBrowserChromeWeak->QueryReferent(aIID, aSink); + } + return mOwnerWin->QueryInterface(aIID, aSink); + } + + if (aIID.Equals(NS_GET_IID(nsIPrompt))) { + nsCOMPtr<nsIPrompt> prompt; + EnsurePrompter(); + prompt = mPrompter; + if (prompt) { + prompt.forget(aSink); + return NS_OK; + } + return NS_NOINTERFACE; + } + + if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) { + nsCOMPtr<nsIAuthPrompt> prompt; + EnsureAuthPrompter(); + prompt = mAuthPrompter; + if (prompt) { + prompt.forget(aSink); + return NS_OK; + } + return NS_NOINTERFACE; + } + + nsCOMPtr<nsIInterfaceRequestor> req = GetOwnerRequestor(); + if (req) { + return req->GetInterface(aIID, aSink); + } + + return NS_NOINTERFACE; +} + +//***************************************************************************** +// nsDocShellTreeOwner::nsIDocShellTreeOwner +//***************************************************************************** + +void +nsDocShellTreeOwner::EnsurePrompter() +{ + if (mPrompter) { + return; + } + + nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); + if (wwatch && mWebBrowser) { + nsCOMPtr<mozIDOMWindowProxy> domWindow; + mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); + if (domWindow) { + wwatch->GetNewPrompter(domWindow, getter_AddRefs(mPrompter)); + } + } +} + +void +nsDocShellTreeOwner::EnsureAuthPrompter() +{ + if (mAuthPrompter) { + return; + } + + nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); + if (wwatch && mWebBrowser) { + nsCOMPtr<mozIDOMWindowProxy> domWindow; + mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); + if (domWindow) { + wwatch->GetNewAuthPrompter(domWindow, getter_AddRefs(mAuthPrompter)); + } + } +} + +void +nsDocShellTreeOwner::AddToWatcher() +{ + if (mWebBrowser) { + nsCOMPtr<mozIDOMWindowProxy> domWindow; + mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); + if (domWindow) { + nsCOMPtr<nsPIWindowWatcher> wwatch( + do_GetService(NS_WINDOWWATCHER_CONTRACTID)); + if (wwatch) { + nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome(); + if (webBrowserChrome) { + wwatch->AddWindow(domWindow, webBrowserChrome); + } + } + } + } +} + +void +nsDocShellTreeOwner::RemoveFromWatcher() +{ + if (mWebBrowser) { + nsCOMPtr<mozIDOMWindowProxy> domWindow; + mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); + if (domWindow) { + nsCOMPtr<nsPIWindowWatcher> wwatch( + do_GetService(NS_WINDOWWATCHER_CONTRACTID)); + if (wwatch) { + wwatch->RemoveWindow(domWindow); + } + } + } +} + +void +nsDocShellTreeOwner::EnsureContentTreeOwner() +{ + if (mContentTreeOwner) { + return; + } + + mContentTreeOwner = new nsDocShellTreeOwner(); + nsCOMPtr<nsIWebBrowserChrome> browserChrome = GetWebBrowserChrome(); + if (browserChrome) { + mContentTreeOwner->SetWebBrowserChrome(browserChrome); + } + + if (mWebBrowser) { + mContentTreeOwner->WebBrowser(mWebBrowser); + } +} + +NS_IMETHODIMP +nsDocShellTreeOwner::ContentShellAdded(nsIDocShellTreeItem* aContentShell, + bool aPrimary, bool aTargetable, + const nsAString& aID) +{ + if (mTreeOwner) + return mTreeOwner->ContentShellAdded(aContentShell, aPrimary, aTargetable, + aID); + + EnsureContentTreeOwner(); + aContentShell->SetTreeOwner(mContentTreeOwner); + + if (aPrimary) { + mPrimaryContentShell = aContentShell; + mPrimaryTabParent = nullptr; + } + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::ContentShellRemoved(nsIDocShellTreeItem* aContentShell) +{ + if (mTreeOwner) { + return mTreeOwner->ContentShellRemoved(aContentShell); + } + + if (mPrimaryContentShell == aContentShell) { + mPrimaryContentShell = nullptr; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetPrimaryContentShell(nsIDocShellTreeItem** aShell) +{ + NS_ENSURE_ARG_POINTER(aShell); + + if (mTreeOwner) { + return mTreeOwner->GetPrimaryContentShell(aShell); + } + + nsCOMPtr<nsIDocShellTreeItem> shell; + if (!mPrimaryTabParent) { + shell = + mPrimaryContentShell ? mPrimaryContentShell : mWebBrowser->mDocShell; + } + shell.forget(aShell); + + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::TabParentAdded(nsITabParent* aTab, bool aPrimary) +{ + if (mTreeOwner) { + return mTreeOwner->TabParentAdded(aTab, aPrimary); + } + + if (aPrimary) { + mPrimaryTabParent = aTab; + mPrimaryContentShell = nullptr; + } else if (mPrimaryTabParent == aTab) { + mPrimaryTabParent = nullptr; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::TabParentRemoved(nsITabParent* aTab) +{ + if (mTreeOwner) { + return mTreeOwner->TabParentRemoved(aTab); + } + + if (aTab == mPrimaryTabParent) { + mPrimaryTabParent = nullptr; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetPrimaryTabParent(nsITabParent** aTab) +{ + if (mTreeOwner) { + return mTreeOwner->GetPrimaryTabParent(aTab); + } + + nsCOMPtr<nsITabParent> tab = mPrimaryTabParent; + tab.forget(aTab); + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetPrimaryContentSize(int32_t* aWidth, + int32_t* aHeight) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetPrimaryContentSize(int32_t aWidth, + int32_t aHeight) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetRootShellSize(int32_t* aWidth, + int32_t* aHeight) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetRootShellSize(int32_t aWidth, + int32_t aHeight) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem, + int32_t aCX, int32_t aCY) +{ + nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome(); + + NS_ENSURE_STATE(mTreeOwner || webBrowserChrome); + + if (mTreeOwner) { + return mTreeOwner->SizeShellTo(aShellItem, aCX, aCY); + } + + if (aShellItem == mWebBrowser->mDocShell) { + nsCOMPtr<nsITabChild> tabChild = do_QueryInterface(webBrowserChrome); + if (tabChild) { + // The XUL window to resize is in the parent process, but there we + // won't be able to get aShellItem to do the hack in nsXULWindow::SizeShellTo, + // so let's send the width and height of aShellItem too. + nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(aShellItem)); + NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE); + + int32_t width = 0; + int32_t height = 0; + shellAsWin->GetSize(&width, &height); + return tabChild->RemoteSizeShellTo(aCX, aCY, width, height); + } + return webBrowserChrome->SizeBrowserTo(aCX, aCY); + } + + nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(aShellItem)); + NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE); + + nsCOMPtr<nsIDOMDocument> domDocument; + webNav->GetDocument(getter_AddRefs(domDocument)); + NS_ENSURE_TRUE(domDocument, NS_ERROR_FAILURE); + + nsCOMPtr<nsIDOMElement> domElement; + domDocument->GetDocumentElement(getter_AddRefs(domElement)); + NS_ENSURE_TRUE(domElement, NS_ERROR_FAILURE); + + // Set the preferred Size + //XXX + NS_ERROR("Implement this"); + /* + Set the preferred size on the aShellItem. + */ + + RefPtr<nsPresContext> presContext; + mWebBrowser->mDocShell->GetPresContext(getter_AddRefs(presContext)); + NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE); + + nsIPresShell* presShell = presContext->GetPresShell(); + NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); + + NS_ENSURE_SUCCESS( + presShell->ResizeReflow(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE), + NS_ERROR_FAILURE); + + nsRect shellArea = presContext->GetVisibleArea(); + + int32_t browserCX = presContext->AppUnitsToDevPixels(shellArea.width); + int32_t browserCY = presContext->AppUnitsToDevPixels(shellArea.height); + + return webBrowserChrome->SizeBrowserTo(browserCX, browserCY); +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetPersistence(bool aPersistPosition, + bool aPersistSize, + bool aPersistSizeMode) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetPersistence(bool* aPersistPosition, + bool* aPersistSize, + bool* aPersistSizeMode) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetTargetableShellCount(uint32_t* aResult) +{ + if (mTreeOwner) { + mTreeOwner->GetTargetableShellCount(aResult); + } else { + *aResult = 0; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetHasPrimaryContent(bool* aResult) +{ + *aResult = mPrimaryTabParent || mPrimaryContentShell; + return NS_OK; +} + +//***************************************************************************** +// nsDocShellTreeOwner::nsIBaseWindow +//***************************************************************************** + +NS_IMETHODIMP +nsDocShellTreeOwner::InitWindow(nativeWindow aParentNativeWindow, + nsIWidget* aParentWidget, int32_t aX, + int32_t aY, int32_t aCX, int32_t aCY) +{ + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::Create() +{ + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::Destroy() +{ + nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome(); + if (webBrowserChrome) { + return webBrowserChrome->DestroyBrowserWindow(); + } + + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetUnscaledDevicePixelsPerCSSPixel(double* aScale) +{ + if (mWebBrowser) { + return mWebBrowser->GetUnscaledDevicePixelsPerCSSPixel(aScale); + } + + *aScale = 1.0; + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetDevicePixelsPerDesktopPixel(double* aScale) +{ + if (mWebBrowser) { + return mWebBrowser->GetDevicePixelsPerDesktopPixel(aScale); + } + + *aScale = 1.0; + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetPositionDesktopPix(int32_t aX, int32_t aY) +{ + if (mWebBrowser) { + nsresult rv = mWebBrowser->SetPositionDesktopPix(aX, aY); + NS_ENSURE_SUCCESS(rv, rv); + } + + double scale = 1.0; + GetDevicePixelsPerDesktopPixel(&scale); + return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale)); +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetPosition(int32_t aX, int32_t aY) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION, + aX, aY, 0, 0); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetPosition(int32_t* aX, int32_t* aY) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION, + aX, aY, nullptr, nullptr); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER, + 0, 0, aCX, aCY); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetSize(int32_t* aCX, int32_t* aCY) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->GetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER, + nullptr, nullptr, aCX, aCY); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aCX, + int32_t aCY, uint32_t aFlags) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->SetDimensions( + nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER | + nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION, + aX, aY, aCX, aCY); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aCX, + int32_t* aCY) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->GetDimensions( + nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER | + nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION, + aX, aY, aCX, aCY); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::Repaint(bool aForce) +{ + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetParentWidget(nsIWidget** aParentWidget) +{ + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetParentWidget(nsIWidget* aParentWidget) +{ + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetParentNativeWindow(nativeWindow* aParentNativeWindow) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->GetSiteWindow(aParentNativeWindow); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow) +{ + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetNativeHandle(nsAString& aNativeHandle) +{ + // the nativeHandle should be accessed from nsIXULWindow + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetVisibility(bool* aVisibility) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->GetVisibility(aVisibility); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetVisibility(bool aVisibility) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->SetVisibility(aVisibility); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetEnabled(bool* aEnabled) +{ + NS_ENSURE_ARG_POINTER(aEnabled); + *aEnabled = true; + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetEnabled(bool aEnabled) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetMainWidget(nsIWidget** aMainWidget) +{ + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetFocus() +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->SetFocus(); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::GetTitle(char16_t** aTitle) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->GetTitle(aTitle); + } + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetTitle(const char16_t* aTitle) +{ + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin(); + if (ownerWin) { + return ownerWin->SetTitle(aTitle); + } + return NS_ERROR_NULL_POINTER; +} + +//***************************************************************************** +// nsDocShellTreeOwner::nsIWebProgressListener +//***************************************************************************** + +NS_IMETHODIMP +nsDocShellTreeOwner::OnProgressChange(nsIWebProgress* aProgress, + nsIRequest* aRequest, + int32_t aCurSelfProgress, + int32_t aMaxSelfProgress, + int32_t aCurTotalProgress, + int32_t aMaxTotalProgress) +{ + // In the absence of DOM document creation event, this method is the + // most convenient place to install the mouse listener on the + // DOM document. + return AddChromeListeners(); +} + +NS_IMETHODIMP +nsDocShellTreeOwner::OnStateChange(nsIWebProgress* aProgress, + nsIRequest* aRequest, + uint32_t aProgressStateFlags, + nsresult aStatus) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsIURI* aURI, + uint32_t aFlags) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::OnStatusChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsresult aStatus, + const char16_t* aMessage) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::OnSecurityChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + uint32_t aState) +{ + return NS_OK; +} + +//***************************************************************************** +// nsDocShellTreeOwner: Accessors +//***************************************************************************** + +void +nsDocShellTreeOwner::WebBrowser(nsWebBrowser* aWebBrowser) +{ + if (!aWebBrowser) { + RemoveChromeListeners(); + } + if (aWebBrowser != mWebBrowser) { + mPrompter = nullptr; + mAuthPrompter = nullptr; + } + + mWebBrowser = aWebBrowser; + + if (mContentTreeOwner) { + mContentTreeOwner->WebBrowser(aWebBrowser); + if (!aWebBrowser) { + mContentTreeOwner = nullptr; + } + } +} + +nsWebBrowser* +nsDocShellTreeOwner::WebBrowser() +{ + return mWebBrowser; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) +{ + if (aTreeOwner) { + nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome(do_GetInterface(aTreeOwner)); + NS_ENSURE_TRUE(webBrowserChrome, NS_ERROR_INVALID_ARG); + NS_ENSURE_SUCCESS(SetWebBrowserChrome(webBrowserChrome), + NS_ERROR_INVALID_ARG); + mTreeOwner = aTreeOwner; + } else { + mTreeOwner = nullptr; + nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome(); + if (!webBrowserChrome) { + NS_ENSURE_SUCCESS(SetWebBrowserChrome(nullptr), NS_ERROR_FAILURE); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::SetWebBrowserChrome(nsIWebBrowserChrome* aWebBrowserChrome) +{ + if (!aWebBrowserChrome) { + mWebBrowserChrome = nullptr; + mOwnerWin = nullptr; + mOwnerRequestor = nullptr; + mWebBrowserChromeWeak = nullptr; + } else { + nsCOMPtr<nsISupportsWeakReference> supportsweak = + do_QueryInterface(aWebBrowserChrome); + if (supportsweak) { + supportsweak->GetWeakReference(getter_AddRefs(mWebBrowserChromeWeak)); + } else { + nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin( + do_QueryInterface(aWebBrowserChrome)); + nsCOMPtr<nsIInterfaceRequestor> requestor( + do_QueryInterface(aWebBrowserChrome)); + + // it's ok for ownerWin or requestor to be null. + mWebBrowserChrome = aWebBrowserChrome; + mOwnerWin = ownerWin; + mOwnerRequestor = requestor; + } + } + + if (mContentTreeOwner) { + mContentTreeOwner->SetWebBrowserChrome(aWebBrowserChrome); + } + + return NS_OK; +} + +// Hook up things to the chrome like context menus and tooltips, if the chrome +// has implemented the right interfaces. +NS_IMETHODIMP +nsDocShellTreeOwner::AddChromeListeners() +{ + nsresult rv = NS_OK; + + nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome(); + if (!webBrowserChrome) { + return NS_ERROR_FAILURE; + } + + // install tooltips + if (!mChromeTooltipListener) { + nsCOMPtr<nsITooltipListener> tooltipListener( + do_QueryInterface(webBrowserChrome)); + if (tooltipListener) { + mChromeTooltipListener = new ChromeTooltipListener(mWebBrowser, + webBrowserChrome); + rv = mChromeTooltipListener->AddChromeListeners(); + } + } + + // install context menus + if (!mChromeContextMenuListener) { + nsCOMPtr<nsIContextMenuListener2> contextListener2( + do_QueryInterface(webBrowserChrome)); + nsCOMPtr<nsIContextMenuListener> contextListener( + do_QueryInterface(webBrowserChrome)); + if (contextListener2 || contextListener) { + mChromeContextMenuListener = + new ChromeContextMenuListener(mWebBrowser, webBrowserChrome); + rv = mChromeContextMenuListener->AddChromeListeners(); + } + } + + // register dragover and drop event listeners with the listener manager + nsCOMPtr<EventTarget> target; + GetDOMEventTarget(mWebBrowser, getter_AddRefs(target)); + + EventListenerManager* elmP = target->GetOrCreateListenerManager(); + if (elmP) { + elmP->AddEventListenerByType(this, NS_LITERAL_STRING("dragover"), + TrustedEventsAtSystemGroupBubble()); + elmP->AddEventListenerByType(this, NS_LITERAL_STRING("drop"), + TrustedEventsAtSystemGroupBubble()); + } + + return rv; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::RemoveChromeListeners() +{ + if (mChromeTooltipListener) { + mChromeTooltipListener->RemoveChromeListeners(); + mChromeTooltipListener = nullptr; + } + if (mChromeContextMenuListener) { + mChromeContextMenuListener->RemoveChromeListeners(); + mChromeContextMenuListener = nullptr; + } + + nsCOMPtr<EventTarget> piTarget; + GetDOMEventTarget(mWebBrowser, getter_AddRefs(piTarget)); + if (!piTarget) { + return NS_OK; + } + + EventListenerManager* elmP = piTarget->GetOrCreateListenerManager(); + if (elmP) { + elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("dragover"), + TrustedEventsAtSystemGroupBubble()); + elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("drop"), + TrustedEventsAtSystemGroupBubble()); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellTreeOwner::HandleEvent(nsIDOMEvent* aEvent) +{ + nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent); + NS_ENSURE_TRUE(dragEvent, NS_ERROR_INVALID_ARG); + + bool defaultPrevented; + aEvent->GetDefaultPrevented(&defaultPrevented); + if (defaultPrevented) { + return NS_OK; + } + + nsCOMPtr<nsIDroppedLinkHandler> handler = + do_GetService("@mozilla.org/content/dropped-link-handler;1"); + if (handler) { + nsAutoString eventType; + aEvent->GetType(eventType); + if (eventType.EqualsLiteral("dragover")) { + bool canDropLink = false; + handler->CanDropLink(dragEvent, false, &canDropLink); + if (canDropLink) { + aEvent->PreventDefault(); + } + } else if (eventType.EqualsLiteral("drop")) { + nsIWebNavigation* webnav = static_cast<nsIWebNavigation*>(mWebBrowser); + + uint32_t linksCount; + nsIDroppedLinkItem** links; + if (webnav && + NS_SUCCEEDED(handler->DropLinks(dragEvent, true, &linksCount, &links))) { + if (linksCount >= 1) { + nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome(); + if (webBrowserChrome) { + nsCOMPtr<nsITabChild> tabChild = do_QueryInterface(webBrowserChrome); + if (tabChild) { + nsresult rv = tabChild->RemoteDropLinks(linksCount, links); + for (uint32_t i = 0; i < linksCount; i++) { + NS_RELEASE(links[i]); + } + free(links); + return rv; + } + } + nsAutoString url; + if (NS_SUCCEEDED(links[0]->GetUrl(url))) { + if (!url.IsEmpty()) { + webnav->LoadURI(url.get(), 0, nullptr, nullptr, nullptr); + } + } + + for (uint32_t i = 0; i < linksCount; i++) { + NS_RELEASE(links[i]); + } + free(links); + } + } else { + aEvent->StopPropagation(); + aEvent->PreventDefault(); + } + } + } + + return NS_OK; +} + +already_AddRefed<nsIWebBrowserChrome> +nsDocShellTreeOwner::GetWebBrowserChrome() +{ + nsCOMPtr<nsIWebBrowserChrome> chrome; + if (mWebBrowserChromeWeak) { + chrome = do_QueryReferent(mWebBrowserChromeWeak); + } else if (mWebBrowserChrome) { + chrome = mWebBrowserChrome; + } + return chrome.forget(); +} + +already_AddRefed<nsIEmbeddingSiteWindow> +nsDocShellTreeOwner::GetOwnerWin() +{ + nsCOMPtr<nsIEmbeddingSiteWindow> win; + if (mWebBrowserChromeWeak) { + win = do_QueryReferent(mWebBrowserChromeWeak); + } else if (mOwnerWin) { + win = mOwnerWin; + } + return win.forget(); +} + +already_AddRefed<nsIInterfaceRequestor> +nsDocShellTreeOwner::GetOwnerRequestor() +{ + nsCOMPtr<nsIInterfaceRequestor> req; + if (mWebBrowserChromeWeak) { + req = do_QueryReferent(mWebBrowserChromeWeak); + } else if (mOwnerRequestor) { + req = mOwnerRequestor; + } + return req.forget(); +} + +NS_IMPL_ISUPPORTS(ChromeTooltipListener, nsIDOMEventListener) + +ChromeTooltipListener::ChromeTooltipListener(nsWebBrowser* aInBrowser, + nsIWebBrowserChrome* aInChrome) + : mWebBrowser(aInBrowser) + , mWebBrowserChrome(aInChrome) + , mTooltipListenerInstalled(false) + , mMouseClientX(0) + , mMouseClientY(0) + , mMouseScreenX(0) + , mMouseScreenY(0) + , mShowingTooltip(false) + , mTooltipShownOnce(false) +{ + mTooltipTextProvider = do_GetService(NS_TOOLTIPTEXTPROVIDER_CONTRACTID); + if (!mTooltipTextProvider) { + mTooltipTextProvider = do_GetService(NS_DEFAULTTOOLTIPTEXTPROVIDER_CONTRACTID); + } +} + +ChromeTooltipListener::~ChromeTooltipListener() +{ +} + +// Hook up things to the chrome like context menus and tooltips, if the chrome +// has implemented the right interfaces. +NS_IMETHODIMP +ChromeTooltipListener::AddChromeListeners() +{ + if (!mEventTarget) { + GetDOMEventTarget(mWebBrowser, getter_AddRefs(mEventTarget)); + } + + // Register the appropriate events for tooltips, but only if + // the embedding chrome cares. + nsresult rv = NS_OK; + nsCOMPtr<nsITooltipListener> tooltipListener( + do_QueryInterface(mWebBrowserChrome)); + if (tooltipListener && !mTooltipListenerInstalled) { + rv = AddTooltipListener(); + if (NS_FAILED(rv)) { + return rv; + } + } + + return rv; +} + +// Subscribe to the events that will allow us to track tooltips. We need "mouse" +// for mouseExit, "mouse motion" for mouseMove, and "key" for keyDown. As we +// add the listeners, keep track of how many succeed so we can clean up +// correctly in Release(). +NS_IMETHODIMP +ChromeTooltipListener::AddTooltipListener() +{ + if (mEventTarget) { + nsresult rv = NS_OK; + rv = mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("keydown"), + this, false, false); + NS_ENSURE_SUCCESS(rv, rv); + rv = mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("mousedown"), + this, false, false); + NS_ENSURE_SUCCESS(rv, rv); + rv = mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("mouseout"), + this, false, false); + NS_ENSURE_SUCCESS(rv, rv); + rv = mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("mousemove"), + this, false, false); + NS_ENSURE_SUCCESS(rv, rv); + + mTooltipListenerInstalled = true; + } + + return NS_OK; +} + +// Unsubscribe from the various things we've hooked up to the window root. +NS_IMETHODIMP +ChromeTooltipListener::RemoveChromeListeners() +{ + HideTooltip(); + + if (mTooltipListenerInstalled) { + RemoveTooltipListener(); + } + + mEventTarget = nullptr; + + // it really doesn't matter if these fail... + return NS_OK; +} + +// Unsubscribe from all the various tooltip events that we were listening to. +NS_IMETHODIMP +ChromeTooltipListener::RemoveTooltipListener() +{ + if (mEventTarget) { + nsresult rv = NS_OK; + rv = mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"), + this, false); + NS_ENSURE_SUCCESS(rv, rv); + rv = mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), + this, false); + NS_ENSURE_SUCCESS(rv, rv); + rv = mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("mouseout"), + this, false); + NS_ENSURE_SUCCESS(rv, rv); + rv = mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("mousemove"), + this, false); + NS_ENSURE_SUCCESS(rv, rv); + + mTooltipListenerInstalled = false; + } + + return NS_OK; +} + +NS_IMETHODIMP +ChromeTooltipListener::HandleEvent(nsIDOMEvent* aEvent) +{ + nsAutoString eventType; + aEvent->GetType(eventType); + + if (eventType.EqualsLiteral("keydown") || + eventType.EqualsLiteral("mousedown")) { + return HideTooltip(); + } else if (eventType.EqualsLiteral("mouseout")) { + // Reset flag so that tooltip will display on the next MouseMove + mTooltipShownOnce = false; + return HideTooltip(); + } else if (eventType.EqualsLiteral("mousemove")) { + return MouseMove(aEvent); + } + + NS_ERROR("Unexpected event type"); + return NS_OK; +} + +// If we're a tooltip, fire off a timer to see if a tooltip should be shown. If +// the timer fires, we cache the node in |mPossibleTooltipNode|. +nsresult +ChromeTooltipListener::MouseMove(nsIDOMEvent* aMouseEvent) +{ + nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aMouseEvent)); + if (!mouseEvent) { + return NS_OK; + } + + // stash the coordinates of the event so that we can still get back to it from + // within the timer callback. On win32, we'll get a MouseMove event even when + // a popup goes away -- even when the mouse doesn't change position! To get + // around this, we make sure the mouse has really moved before proceeding. + int32_t newMouseX, newMouseY; + mouseEvent->GetClientX(&newMouseX); + mouseEvent->GetClientY(&newMouseY); + if (mMouseClientX == newMouseX && mMouseClientY == newMouseY) { + return NS_OK; + } + + // Filter out minor mouse movements. + if (mShowingTooltip && + (abs(mMouseClientX - newMouseX) <= kTooltipMouseMoveTolerance) && + (abs(mMouseClientY - newMouseY) <= kTooltipMouseMoveTolerance)) { + return NS_OK; + } + + mMouseClientX = newMouseX; + mMouseClientY = newMouseY; + mouseEvent->GetScreenX(&mMouseScreenX); + mouseEvent->GetScreenY(&mMouseScreenY); + + if (mTooltipTimer) { + mTooltipTimer->Cancel(); + } + + if (!mShowingTooltip && !mTooltipShownOnce) { + mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1"); + if (mTooltipTimer) { + nsCOMPtr<EventTarget> eventTarget = + aMouseEvent->InternalDOMEvent()->GetTarget(); + if (eventTarget) { + mPossibleTooltipNode = do_QueryInterface(eventTarget); + } + if (mPossibleTooltipNode) { + nsresult rv = mTooltipTimer->InitWithFuncCallback( + sTooltipCallback, this, + LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500), + nsITimer::TYPE_ONE_SHOT); + if (NS_FAILED(rv)) { + mPossibleTooltipNode = nullptr; + } + } + } else { + NS_WARNING("Could not create a timer for tooltip tracking"); + } + } else { + mTooltipShownOnce = true; + return HideTooltip(); + } + + return NS_OK; +} + +// Tell the registered chrome that they should show the tooltip. +NS_IMETHODIMP +ChromeTooltipListener::ShowTooltip(int32_t aInXCoords, int32_t aInYCoords, + const nsAString& aInTipText, + const nsAString& aTipDir) +{ + nsresult rv = NS_OK; + + // do the work to call the client + nsCOMPtr<nsITooltipListener> tooltipListener( + do_QueryInterface(mWebBrowserChrome)); + if (tooltipListener) { + rv = tooltipListener->OnShowTooltip(aInXCoords, aInYCoords, + PromiseFlatString(aInTipText).get(), + PromiseFlatString(aTipDir).get()); + if (NS_SUCCEEDED(rv)) { + mShowingTooltip = true; + } + } + + return rv; +} + +// Tell the registered chrome that they should rollup the tooltip +// NOTE: This routine is safe to call even if the popup is already closed. +NS_IMETHODIMP +ChromeTooltipListener::HideTooltip() +{ + nsresult rv = NS_OK; + + // shut down the relevant timers + if (mTooltipTimer) { + mTooltipTimer->Cancel(); + mTooltipTimer = nullptr; + // release tooltip target + mPossibleTooltipNode = nullptr; + } + + // if we're showing the tip, tell the chrome to hide it + if (mShowingTooltip) { + nsCOMPtr<nsITooltipListener> tooltipListener( + do_QueryInterface(mWebBrowserChrome)); + if (tooltipListener) { + rv = tooltipListener->OnHideTooltip(); + if (NS_SUCCEEDED(rv)) { + mShowingTooltip = false; + } + } + } + + return rv; +} + +// A timer callback, fired when the mouse has hovered inside of a frame for the +// appropriate amount of time. Getting to this point means that we should show +// the tooltip, but only after we determine there is an appropriate TITLE +// element. +// +// This relies on certain things being cached into the |aChromeTooltipListener| +// object passed to us by the timer: +// -- the x/y coordinates of the mouse (mMouseClientY, mMouseClientX) +// -- the dom node the user hovered over (mPossibleTooltipNode) +void +ChromeTooltipListener::sTooltipCallback(nsITimer* aTimer, + void* aChromeTooltipListener) +{ + auto self = static_cast<ChromeTooltipListener*>(aChromeTooltipListener); + if (self && self->mPossibleTooltipNode) { + // The actual coordinates we want to put the tooltip at are relative to the + // toplevel docshell of our mWebBrowser. We know what the screen + // coordinates of the mouse event were, which means we just need the screen + // coordinates of the docshell. Unfortunately, there is no good way to + // find those short of groveling for the presentation in that docshell and + // finding the screen coords of its toplevel widget... + nsCOMPtr<nsIDocShell> docShell = + do_GetInterface(static_cast<nsIWebBrowser*>(self->mWebBrowser)); + nsCOMPtr<nsIPresShell> shell; + if (docShell) { + shell = docShell->GetPresShell(); + } + + nsIWidget* widget = nullptr; + if (shell) { + nsViewManager* vm = shell->GetViewManager(); + if (vm) { + nsView* view = vm->GetRootView(); + if (view) { + nsPoint offset; + widget = view->GetNearestWidget(&offset); + } + } + } + + if (!widget) { + // release tooltip target if there is one, NO MATTER WHAT + self->mPossibleTooltipNode = nullptr; + return; + } + + // if there is text associated with the node, show the tip and fire + // off a timer to auto-hide it. + + nsXPIDLString tooltipText; + nsXPIDLString directionText; + if (self->mTooltipTextProvider) { + bool textFound = false; + + self->mTooltipTextProvider->GetNodeText( + self->mPossibleTooltipNode, getter_Copies(tooltipText), + getter_Copies(directionText), &textFound); + + if (textFound) { + nsString tipText(tooltipText); + nsString dirText(directionText); + LayoutDeviceIntPoint screenDot = widget->WidgetToScreenOffset(); + double scaleFactor = 1.0; + if (shell->GetPresContext()) { + nsDeviceContext* dc = shell->GetPresContext()->DeviceContext(); + scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel()) / + dc->AppUnitsPerDevPixelAtUnitFullZoom(); + } + // ShowTooltip expects widget-relative position. + self->ShowTooltip(self->mMouseScreenX - screenDot.x / scaleFactor, + self->mMouseScreenY - screenDot.y / scaleFactor, + tipText, dirText); + } + } + + // release tooltip target if there is one, NO MATTER WHAT + self->mPossibleTooltipNode = nullptr; + } +} + +NS_IMPL_ISUPPORTS(ChromeContextMenuListener, nsIDOMEventListener) + +ChromeContextMenuListener::ChromeContextMenuListener( + nsWebBrowser* aInBrowser, + nsIWebBrowserChrome* aInChrome) + : mContextMenuListenerInstalled(false) + , mWebBrowser(aInBrowser) + , mWebBrowserChrome(aInChrome) +{ +} + +ChromeContextMenuListener::~ChromeContextMenuListener() +{ +} + +// Subscribe to the events that will allow us to track context menus. Bascially, +// this is just the context-menu DOM event. +NS_IMETHODIMP +ChromeContextMenuListener::AddContextMenuListener() +{ + if (mEventTarget) { + nsresult rv = mEventTarget->AddEventListener( + NS_LITERAL_STRING("contextmenu"), this, false, false); + NS_ENSURE_SUCCESS(rv, rv); + + mContextMenuListenerInstalled = true; + } + + return NS_OK; +} + +// Unsubscribe from all the various context menu events that we were listening +// to. +NS_IMETHODIMP +ChromeContextMenuListener::RemoveContextMenuListener() +{ + if (mEventTarget) { + nsresult rv = mEventTarget->RemoveEventListener( + NS_LITERAL_STRING("contextmenu"), this, false); + NS_ENSURE_SUCCESS(rv, rv); + + mContextMenuListenerInstalled = false; + } + + return NS_OK; +} + +// Hook up things to the chrome like context menus and tooltips, if the chrome +// has implemented the right interfaces. +NS_IMETHODIMP +ChromeContextMenuListener::AddChromeListeners() +{ + if (!mEventTarget) { + GetDOMEventTarget(mWebBrowser, getter_AddRefs(mEventTarget)); + } + + // Register the appropriate events for context menus, but only if + // the embedding chrome cares. + nsresult rv = NS_OK; + + nsCOMPtr<nsIContextMenuListener2> contextListener2( + do_QueryInterface(mWebBrowserChrome)); + nsCOMPtr<nsIContextMenuListener> contextListener( + do_QueryInterface(mWebBrowserChrome)); + if ((contextListener || contextListener2) && !mContextMenuListenerInstalled) { + rv = AddContextMenuListener(); + } + + return rv; +} + +// Unsubscribe from the various things we've hooked up to the window root. +NS_IMETHODIMP +ChromeContextMenuListener::RemoveChromeListeners() +{ + if (mContextMenuListenerInstalled) { + RemoveContextMenuListener(); + } + + mEventTarget = nullptr; + + // it really doesn't matter if these fail... + return NS_OK; +} + +// We're on call to show the context menu. Dig around in the DOM to find the +// type of object we're dealing with and notify the front end chrome. +NS_IMETHODIMP +ChromeContextMenuListener::HandleEvent(nsIDOMEvent* aMouseEvent) +{ + nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent); + NS_ENSURE_TRUE(mouseEvent, NS_ERROR_UNEXPECTED); + + bool isDefaultPrevented = false; + aMouseEvent->GetDefaultPrevented(&isDefaultPrevented); + if (isDefaultPrevented) { + return NS_OK; + } + + nsCOMPtr<EventTarget> targetNode = + aMouseEvent->InternalDOMEvent()->GetTarget(); + if (!targetNode) { + return NS_ERROR_NULL_POINTER; + } + + nsCOMPtr<nsIDOMNode> targetDOMnode; + nsCOMPtr<nsIDOMNode> node = do_QueryInterface(targetNode); + if (!node) { + return NS_OK; + } + + // Stop the context menu event going to other windows (bug 78396) + aMouseEvent->PreventDefault(); + + // If the listener is a nsIContextMenuListener2, create the info object + nsCOMPtr<nsIContextMenuListener2> menuListener2( + do_QueryInterface(mWebBrowserChrome)); + nsContextMenuInfo* menuInfoImpl = nullptr; + nsCOMPtr<nsIContextMenuInfo> menuInfo; + if (menuListener2) { + menuInfoImpl = new nsContextMenuInfo; + menuInfo = menuInfoImpl; + } + + uint32_t flags = nsIContextMenuListener::CONTEXT_NONE; + uint32_t flags2 = nsIContextMenuListener2::CONTEXT_NONE; + + // XXX test for selected text + + uint16_t nodeType; + nsresult res = node->GetNodeType(&nodeType); + NS_ENSURE_SUCCESS(res, res); + + // First, checks for nodes that never have children. + if (nodeType == nsIDOMNode::ELEMENT_NODE) { + nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(node)); + if (content) { + nsCOMPtr<nsIURI> imgUri; + content->GetCurrentURI(getter_AddRefs(imgUri)); + if (imgUri) { + flags |= nsIContextMenuListener::CONTEXT_IMAGE; + flags2 |= nsIContextMenuListener2::CONTEXT_IMAGE; + targetDOMnode = node; + } + } + + nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(node)); + if (formControl) { + if (formControl->GetType() == NS_FORM_TEXTAREA) { + flags |= nsIContextMenuListener::CONTEXT_TEXT; + flags2 |= nsIContextMenuListener2::CONTEXT_TEXT; + targetDOMnode = node; + } else { + nsCOMPtr<nsIDOMHTMLInputElement> inputElement( + do_QueryInterface(formControl)); + if (inputElement) { + flags |= nsIContextMenuListener::CONTEXT_INPUT; + flags2 |= nsIContextMenuListener2::CONTEXT_INPUT; + + if (menuListener2) { + if (formControl->IsSingleLineTextControl(false)) { + flags2 |= nsIContextMenuListener2::CONTEXT_TEXT; + } + } + + targetDOMnode = node; + } + } + } + + // always consume events for plugins and Java who may throw their + // own context menus but not for image objects. Document objects + // will never be targets or ancestors of targets, so that's OK. + nsCOMPtr<nsIDOMHTMLObjectElement> objectElement; + if (!(flags & nsIContextMenuListener::CONTEXT_IMAGE)) { + objectElement = do_QueryInterface(node); + } + nsCOMPtr<nsIDOMHTMLEmbedElement> embedElement(do_QueryInterface(node)); + nsCOMPtr<nsIDOMHTMLAppletElement> appletElement(do_QueryInterface(node)); + + if (objectElement || embedElement || appletElement) { + return NS_OK; + } + } + + // Bubble out, looking for items of interest + do { + uint16_t nodeType; + res = node->GetNodeType(&nodeType); + NS_ENSURE_SUCCESS(res, res); + + if (nodeType == nsIDOMNode::ELEMENT_NODE) { + + // Test if the element has an associated link + nsCOMPtr<nsIDOMElement> element(do_QueryInterface(node)); + + bool hasAttr = false; + res = element->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr); + + if (NS_SUCCEEDED(res) && hasAttr) { + flags |= nsIContextMenuListener::CONTEXT_LINK; + flags2 |= nsIContextMenuListener2::CONTEXT_LINK; + if (!targetDOMnode) { + targetDOMnode = node; + } + if (menuInfoImpl) { + menuInfoImpl->SetAssociatedLink(node); + } + break; // exit do-while + } + } + + // walk-up-the-tree + nsCOMPtr<nsIDOMNode> parentNode; + node->GetParentNode(getter_AddRefs(parentNode)); + node = parentNode; + } while (node); + + if (!flags && !flags2) { + // We found nothing of interest so far, check if we + // have at least an html document. + nsCOMPtr<nsIDOMDocument> document; + node = do_QueryInterface(targetNode); + node->GetOwnerDocument(getter_AddRefs(document)); + nsCOMPtr<nsIDOMHTMLDocument> htmlDocument(do_QueryInterface(document)); + if (htmlDocument) { + flags |= nsIContextMenuListener::CONTEXT_DOCUMENT; + flags2 |= nsIContextMenuListener2::CONTEXT_DOCUMENT; + targetDOMnode = node; + if (!(flags & nsIContextMenuListener::CONTEXT_IMAGE)) { + // check if this is a background image that the user was trying to click + // on and if the listener is ready for that (only + // nsIContextMenuListener2 and up) + if (menuInfoImpl && menuInfoImpl->HasBackgroundImage(targetDOMnode)) { + flags2 |= nsIContextMenuListener2::CONTEXT_BACKGROUND_IMAGE; + // For the embedder to get the correct background image + // targetDOMnode must point to the original node. + targetDOMnode = do_QueryInterface(targetNode); + } + } + } + } + + // we need to cache the event target into the focus controller's popupNode + // so we can get at it later from command code, etc.: + + // get the dom window + nsCOMPtr<mozIDOMWindowProxy> win; + res = mWebBrowser->GetContentDOMWindow(getter_AddRefs(win)); + NS_ENSURE_SUCCESS(res, res); + NS_ENSURE_TRUE(win, NS_ERROR_FAILURE); + + auto* window = nsPIDOMWindowOuter::From(win); + nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot(); + NS_ENSURE_TRUE(root, NS_ERROR_FAILURE); + if (root) { + // set the window root's popup node to the event target + root->SetPopupNode(targetDOMnode); + } + + // Tell the listener all about the event + if (menuListener2) { + menuInfoImpl->SetMouseEvent(aMouseEvent); + menuInfoImpl->SetDOMNode(targetDOMnode); + menuListener2->OnShowContextMenu(flags2, menuInfo); + } else { + nsCOMPtr<nsIContextMenuListener> menuListener( + do_QueryInterface(mWebBrowserChrome)); + if (menuListener) { + menuListener->OnShowContextMenu(flags, aMouseEvent, targetDOMnode); + } + } + + return NS_OK; +} diff --git a/embedding/browser/nsDocShellTreeOwner.h b/embedding/browser/nsDocShellTreeOwner.h new file mode 100644 index 000000000..d935ba165 --- /dev/null +++ b/embedding/browser/nsDocShellTreeOwner.h @@ -0,0 +1,246 @@ +/* -*- 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 nsDocShellTreeOwner_h__ +#define nsDocShellTreeOwner_h__ + +// Helper Classes +#include "nsCOMPtr.h" +#include "nsString.h" + +// Interfaces Needed +#include "nsIBaseWindow.h" +#include "nsIDocShellTreeOwner.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIWebBrowserChrome.h" +#include "nsIDOMEventListener.h" +#include "nsIEmbeddingSiteWindow.h" +#include "nsIWebProgressListener.h" +#include "nsWeakReference.h" +#include "nsITimer.h" +#include "nsIPrompt.h" +#include "nsIAuthPrompt.h" +#include "nsITooltipListener.h" +#include "nsITooltipTextProvider.h" +#include "nsCTooltipTextProvider.h" +#include "nsIDroppedLinkHandler.h" +#include "nsCommandHandler.h" + +namespace mozilla { +namespace dom { +class EventTarget; +} // namespace dom +} // namespace mozilla + +class nsWebBrowser; +class ChromeTooltipListener; +class ChromeContextMenuListener; + +// {6D10C180-6888-11d4-952B-0020183BF181} +#define NS_ICDOCSHELLTREEOWNER_IID \ + { 0x6d10c180, 0x6888, 0x11d4, { 0x95, 0x2b, 0x0, 0x20, 0x18, 0x3b, 0xf1, 0x81 } } + +// This is a fake 'hidden' interface that nsDocShellTreeOwner implements. +// Classes such as nsCommandHandler can QI for this interface to be sure that +// they're dealing with a valid nsDocShellTreeOwner and not some other object +// that implements nsIDocShellTreeOwner. +class nsICDocShellTreeOwner : public nsISupports +{ +public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICDOCSHELLTREEOWNER_IID) +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsICDocShellTreeOwner, NS_ICDOCSHELLTREEOWNER_IID) + +class nsDocShellTreeOwner final : public nsIDocShellTreeOwner, + public nsIBaseWindow, + public nsIInterfaceRequestor, + public nsIWebProgressListener, + public nsIDOMEventListener, + public nsICDocShellTreeOwner, + public nsSupportsWeakReference +{ + friend class nsWebBrowser; + friend class nsCommandHandler; + +public: + NS_DECL_ISUPPORTS + + NS_DECL_NSIBASEWINDOW + NS_DECL_NSIDOCSHELLTREEOWNER + NS_DECL_NSIDOMEVENTLISTENER + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSIWEBPROGRESSLISTENER + +protected: + nsDocShellTreeOwner(); + virtual ~nsDocShellTreeOwner(); + + void WebBrowser(nsWebBrowser* aWebBrowser); + + nsWebBrowser* WebBrowser(); + NS_IMETHOD SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner); + NS_IMETHOD SetWebBrowserChrome(nsIWebBrowserChrome* aWebBrowserChrome); + + NS_IMETHOD AddChromeListeners(); + NS_IMETHOD RemoveChromeListeners(); + + nsresult FindItemWithNameAcrossWindows( + const char16_t* aName, + nsIDocShellTreeItem* aRequestor, nsIDocShellTreeItem* aOriginalRequestor, + nsIDocShellTreeItem** aFoundItem); + + void EnsurePrompter(); + void EnsureAuthPrompter(); + + void AddToWatcher(); + void RemoveFromWatcher(); + + void EnsureContentTreeOwner(); + + // These helper functions return the correct instances of the requested + // interfaces. If the object passed to SetWebBrowserChrome() implements + // nsISupportsWeakReference, then these functions call QueryReferent on + // that object. Otherwise, they return an addrefed pointer. If the + // WebBrowserChrome object doesn't exist, they return nullptr. + already_AddRefed<nsIWebBrowserChrome> GetWebBrowserChrome(); + already_AddRefed<nsIEmbeddingSiteWindow> GetOwnerWin(); + already_AddRefed<nsIInterfaceRequestor> GetOwnerRequestor(); + +protected: + // Weak References + nsWebBrowser* mWebBrowser; + nsIDocShellTreeOwner* mTreeOwner; + nsIDocShellTreeItem* mPrimaryContentShell; + + nsIWebBrowserChrome* mWebBrowserChrome; + nsIEmbeddingSiteWindow* mOwnerWin; + nsIInterfaceRequestor* mOwnerRequestor; + + nsWeakPtr mWebBrowserChromeWeak; // nsIWebBrowserChrome + + // the objects that listen for chrome events like context menus and tooltips. + // They are separate objects to avoid circular references between |this| + // and the DOM. + RefPtr<ChromeTooltipListener> mChromeTooltipListener; + RefPtr<ChromeContextMenuListener> mChromeContextMenuListener; + + RefPtr<nsDocShellTreeOwner> mContentTreeOwner; + + nsCOMPtr<nsIPrompt> mPrompter; + nsCOMPtr<nsIAuthPrompt> mAuthPrompter; + nsCOMPtr<nsITabParent> mPrimaryTabParent; +}; + + +// The class that listens to the chrome events and tells the embedding chrome to +// show tooltips, as appropriate. Handles registering itself with the DOM with +// AddChromeListeners() and removing itself with RemoveChromeListeners(). +class ChromeTooltipListener final : public nsIDOMEventListener +{ +protected: + virtual ~ChromeTooltipListener(); + +public: + NS_DECL_ISUPPORTS + + ChromeTooltipListener(nsWebBrowser* aInBrowser, nsIWebBrowserChrome* aInChrome); + + NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override; + NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent); + + // Add/remove the relevant listeners, based on what interfaces the embedding + // chrome implements. + NS_IMETHOD AddChromeListeners(); + NS_IMETHOD RemoveChromeListeners(); + +private: + // various delays for tooltips + enum + { + kTooltipAutoHideTime = 5000, // ms + kTooltipMouseMoveTolerance = 7 // pixel tolerance for mousemove event + }; + + NS_IMETHOD AddTooltipListener(); + NS_IMETHOD RemoveTooltipListener(); + + NS_IMETHOD ShowTooltip(int32_t aInXCoords, int32_t aInYCoords, + const nsAString& aInTipText, + const nsAString& aDirText); + NS_IMETHOD HideTooltip(); + + nsWebBrowser* mWebBrowser; + nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; + nsCOMPtr<nsITooltipTextProvider> mTooltipTextProvider; + + // This must be a strong ref in order to make sure we can hide the tooltip if + // the window goes away while we're displaying one. If we don't hold a strong + // ref, the chrome might have been disposed of before we get a chance to tell + // it, and no one would ever tell us of that fact. + nsCOMPtr<nsIWebBrowserChrome> mWebBrowserChrome; + + bool mTooltipListenerInstalled; + + nsCOMPtr<nsITimer> mTooltipTimer; + static void sTooltipCallback(nsITimer* aTimer, void* aListener); + + // Mouse coordinates for last mousemove event we saw + int32_t mMouseClientX; + int32_t mMouseClientY; + + // Mouse coordinates for tooltip event + int32_t mMouseScreenX; + int32_t mMouseScreenY; + + bool mShowingTooltip; + bool mTooltipShownOnce; + + // The node hovered over that fired the timer. This may turn into the node + // that triggered the tooltip, but only if the timer ever gets around to + // firing. This is a strong reference, because the tooltip content can be + // destroyed while we're waiting for the tooltip to pup up, and we need to + // detect that. It's set only when the tooltip timer is created and launched. + // The timer must either fire or be cancelled (or possibly released?), and we + // release this reference in each of those cases. So we don't leak. + nsCOMPtr<nsIDOMNode> mPossibleTooltipNode; +}; + +// The class that listens to the chrome events and tells the embedding chrome to +// show context menus, as appropriate. Handles registering itself with the DOM +// with AddChromeListeners() and removing itself with RemoveChromeListeners(). +class ChromeContextMenuListener : public nsIDOMEventListener +{ +protected: + virtual ~ChromeContextMenuListener(); + +public: + NS_DECL_ISUPPORTS + + ChromeContextMenuListener(nsWebBrowser* aInBrowser, + nsIWebBrowserChrome* aInChrome); + + // nsIDOMContextMenuListener + NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override; + + // Add/remove the relevant listeners, based on what interfaces + // the embedding chrome implements. + NS_IMETHOD AddChromeListeners(); + NS_IMETHOD RemoveChromeListeners(); + +private: + NS_IMETHOD AddContextMenuListener(); + NS_IMETHOD RemoveContextMenuListener(); + + bool mContextMenuListenerInstalled; + + nsWebBrowser* mWebBrowser; + nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; + nsCOMPtr<nsIWebBrowserChrome> mWebBrowserChrome; +}; + +#endif /* nsDocShellTreeOwner_h__ */ diff --git a/embedding/browser/nsEmbedStream.cpp b/embedding/browser/nsEmbedStream.cpp new file mode 100644 index 000000000..35347060c --- /dev/null +++ b/embedding/browser/nsEmbedStream.cpp @@ -0,0 +1,101 @@ +/* -*- 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 "nsIAsyncInputStream.h" +#include "nsIAsyncOutputStream.h" +#include "nsIDocShell.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIPipe.h" + +#include "nsEmbedStream.h" +#include "nsError.h" +#include "nsString.h" + +NS_IMPL_ISUPPORTS0(nsEmbedStream) + +nsEmbedStream::nsEmbedStream() +{ + mOwner = nullptr; +} + +nsEmbedStream::~nsEmbedStream() +{ +} + +void +nsEmbedStream::InitOwner(nsIWebBrowser* aOwner) +{ + mOwner = aOwner; +} + +nsresult +nsEmbedStream::Init(void) +{ + return NS_OK; +} + +nsresult +nsEmbedStream::OpenStream(nsIURI* aBaseURI, const nsACString& aContentType) +{ + nsresult rv; + NS_ENSURE_ARG_POINTER(aBaseURI); + NS_ENSURE_TRUE(IsASCII(aContentType), NS_ERROR_INVALID_ARG); + + // if we're already doing a stream, return an error + if (mOutputStream) { + return NS_ERROR_IN_PROGRESS; + } + + nsCOMPtr<nsIAsyncInputStream> inputStream; + nsCOMPtr<nsIAsyncOutputStream> outputStream; + rv = NS_NewPipe2(getter_AddRefs(inputStream), getter_AddRefs(outputStream), + true, false, 0, UINT32_MAX); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mOwner); + rv = docShell->LoadStream(inputStream, aBaseURI, aContentType, + EmptyCString(), nullptr); + if (NS_FAILED(rv)) { + return rv; + } + + mOutputStream = outputStream; + return rv; +} + +nsresult +nsEmbedStream::AppendToStream(const uint8_t* aData, uint32_t aLen) +{ + nsresult rv; + NS_ENSURE_STATE(mOutputStream); + + uint32_t bytesWritten = 0; + rv = mOutputStream->Write(reinterpret_cast<const char*>(aData), + aLen, &bytesWritten); + if (NS_FAILED(rv)) { + return rv; + } + + NS_ASSERTION(bytesWritten == aLen, + "underlying buffer couldn't handle the write"); + return rv; +} + +nsresult +nsEmbedStream::CloseStream(void) +{ + nsresult rv = NS_OK; + + // NS_ENSURE_STATE returns NS_ERROR_UNEXPECTED if the condition isn't + // satisfied; this is exactly what we want to return. + NS_ENSURE_STATE(mOutputStream); + mOutputStream->Close(); + mOutputStream = nullptr; + + return rv; +} diff --git a/embedding/browser/nsEmbedStream.h b/embedding/browser/nsEmbedStream.h new file mode 100644 index 000000000..03dca7936 --- /dev/null +++ b/embedding/browser/nsEmbedStream.h @@ -0,0 +1,37 @@ +/* -*- 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 nsEmbedStream_h__ +#define nsEmbedStream_h__ + +#include "nsCOMPtr.h" +#include "nsIOutputStream.h" +#include "nsIURI.h" +#include "nsIWebBrowser.h" + +class nsEmbedStream : public nsISupports +{ +public: + nsEmbedStream(); + + void InitOwner(nsIWebBrowser* aOwner); + nsresult Init(void); + + nsresult OpenStream(nsIURI* aBaseURI, const nsACString& aContentType); + nsresult AppendToStream(const uint8_t* aData, uint32_t aLen); + nsresult CloseStream(void); + + NS_DECL_ISUPPORTS + +protected: + virtual ~nsEmbedStream(); + +private: + nsIWebBrowser* mOwner; + nsCOMPtr<nsIOutputStream> mOutputStream; +}; + +#endif // nsEmbedStream_h__ diff --git a/embedding/browser/nsICommandHandler.idl b/embedding/browser/nsICommandHandler.idl new file mode 100644 index 000000000..15a2fd23b --- /dev/null +++ b/embedding/browser/nsICommandHandler.idl @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface mozIDOMWindowProxy; + +[scriptable, uuid(08aed3cc-69f7-47ba-a110-f2efa8a6d7ea)] +interface nsICommandHandlerInit : nsISupports +{ + attribute mozIDOMWindowProxy window; +}; + +[scriptable, uuid(34A4FCF0-66FC-11d4-9528-0020183BF181)] +interface nsICommandHandler : nsISupports +{ + /* + * Execute the specified command with the specified parameters and return + * the result to the caller. The format of the command, parameters and + * the result are determined by the acutal implementation. + */ + string exec(in string aCommand, in string aParameters); + /* + * Query the status of the specified command with the specified parameters + * and return the result to the caller. The format of the command, + * parameters and the result are determined by the implementation. + */ + string query(in string aCommand, in string aParameters); +}; + +%{ C++ +// {3A449110-66FD-11d4-9528-0020183BF181} - +#define NS_COMMANDHANDLER_CID \ +{ 0x3a449110, 0x66fd, 0x11d4, { 0x95, 0x28, 0x0, 0x20, 0x18, 0x3b, 0xf1, 0x81 } } +#define NS_COMMANDHANDLER_CONTRACTID \ +"@mozilla.org/embedding/browser/nsCommandHandler;1" +%} + diff --git a/embedding/browser/nsIContextMenuListener.idl b/embedding/browser/nsIContextMenuListener.idl new file mode 100644 index 000000000..2e4d1c1e9 --- /dev/null +++ b/embedding/browser/nsIContextMenuListener.idl @@ -0,0 +1,65 @@ +/* -*- 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 nsIDOMEvent; +interface nsIDOMNode; + +/** + * An optional interface for embedding clients wishing to receive + * notifications for context menu events (e.g. generated by + * a user right-mouse clicking on a link). The embedder implements + * this interface on the web browser chrome object associated + * with the window that notifications are required for. When a context + * menu event, the browser will call this interface if present. + * + * @see nsIDOMNode + * @see nsIDOMEvent + */ +[scriptable, uuid(3478b6b0-3875-11d4-94ef-0020183bf181)] +interface nsIContextMenuListener : nsISupports +{ + /** Flag. No context. */ + const unsigned long CONTEXT_NONE = 0; + /** Flag. Context is a link element. */ + const unsigned long CONTEXT_LINK = 1; + /** Flag. Context is an image element. */ + const unsigned long CONTEXT_IMAGE = 2; + /** Flag. Context is the whole document. */ + const unsigned long CONTEXT_DOCUMENT = 4; + /** Flag. Context is a text area element. */ + const unsigned long CONTEXT_TEXT = 8; + /** Flag. Context is an input element. */ + const unsigned long CONTEXT_INPUT = 16; + + /** + * Called when the browser receives a context menu event (e.g. user is right-mouse + * clicking somewhere on the document). The combination of flags, event and node + * provided in the call indicate where and what was clicked on. + * + * The following table describes what context flags and node combinations are + * possible. + * + * <TABLE> + * <TR><TD><B>aContextFlag</B></TD><TD>aNode</TD></TR> + * <TR><TD>CONTEXT_LINK</TD><TD><A></TD></TR> + * <TR><TD>CONTEXT_IMAGE</TD><TD><IMG></TD></TR> + * <TR><TD>CONTEXT_IMAGE | CONTEXT_LINK</TD><TD><IMG> + * with an <A> as an ancestor</TD></TR> + * <TR><TD>CONTEXT_INPUT</TD><TD><INPUT></TD></TR> + * <TR><TD>CONTEXT_TEXT</TD><TD><TEXTAREA></TD></TR> + * <TR><TD>CONTEXT_DOCUMENT</TD><TD><HTML></TD></TR> + * </TABLE> + * + * @param aContextFlags Flags indicating the kind of context. + * @param aEvent The DOM context menu event. + * @param aNode The DOM node most relevant to the context. + * + * @return <CODE>NS_OK</CODE> always. + */ + void onShowContextMenu(in unsigned long aContextFlags, in nsIDOMEvent aEvent, in nsIDOMNode aNode); +}; + diff --git a/embedding/browser/nsIContextMenuListener2.idl b/embedding/browser/nsIContextMenuListener2.idl new file mode 100644 index 000000000..19d898011 --- /dev/null +++ b/embedding/browser/nsIContextMenuListener2.idl @@ -0,0 +1,121 @@ +/* -*- Mode: IDL; tab-width: 2; 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 nsIDOMEvent; +interface nsIDOMNode; +interface imgIContainer; +interface nsIURI; +interface nsIContextMenuInfo; + +/* THIS IS A PUBLIC EMBEDDING API */ + +/** + * nsIContextMenuListener2 + * + * This is an extended version of nsIContextMenuListener + * It provides a helper class, nsIContextMenuInfo, to allow access to + * background images as well as various utilities. + * + * @see nsIContextMenuListener + * @see nsIContextMenuInfo + */ + +[scriptable, uuid(7fb719b3-d804-4964-9596-77cf924ee314)] +interface nsIContextMenuListener2 : nsISupports +{ + /** Flag. No context. */ + const unsigned long CONTEXT_NONE = 0; + /** Flag. Context is a link element. */ + const unsigned long CONTEXT_LINK = 1; + /** Flag. Context is an image element. */ + const unsigned long CONTEXT_IMAGE = 2; + /** Flag. Context is the whole document. */ + const unsigned long CONTEXT_DOCUMENT = 4; + /** Flag. Context is a text area element. */ + const unsigned long CONTEXT_TEXT = 8; + /** Flag. Context is an input element. */ + const unsigned long CONTEXT_INPUT = 16; + /** Flag. Context is a background image. */ + const unsigned long CONTEXT_BACKGROUND_IMAGE = 32; + + /** + * Called when the browser receives a context menu event (e.g. user is right-mouse + * clicking somewhere on the document). The combination of flags, along with the + * attributes of <CODE>aUtils</CODE>, indicate where and what was clicked on. + * + * The following table describes what context flags and node combinations are + * possible. + * + * aContextFlags aUtils.targetNode + * + * CONTEXT_LINK <A> + * CONTEXT_IMAGE <IMG> + * CONTEXT_IMAGE | CONTEXT_LINK <IMG> with <A> as an ancestor + * CONTEXT_INPUT <INPUT> + * CONTEXT_INPUT | CONTEXT_IMAGE <INPUT> with type=image + * CONTEXT_TEXT <TEXTAREA> + * CONTEXT_DOCUMENT <HTML> + * CONTEXT_BACKGROUND_IMAGE <HTML> with background image + * + * @param aContextFlags Flags indicating the kind of context. + * @param aUtils Context information and helper utilities. + * + * @see nsIContextMenuInfo + */ + void onShowContextMenu(in unsigned long aContextFlags, in nsIContextMenuInfo aUtils); +}; + +/** + * nsIContextMenuInfo + * + * A helper object for implementors of nsIContextMenuListener2. + */ + +[scriptable, uuid(2f977d56-5485-11d4-87e2-0010a4e75ef2)] +interface nsIContextMenuInfo : nsISupports +{ + /** + * The DOM context menu event. + */ + readonly attribute nsIDOMEvent mouseEvent; + + /** + * The DOM node most relevant to the context. + */ + readonly attribute nsIDOMNode targetNode; + + /** + * Given the <CODE>CONTEXT_LINK</CODE> flag, <CODE>targetNode</CODE> may not + * nescesarily be a link. This returns the anchor from <CODE>targetNode</CODE> + * if it has one or that of its nearest ancestor if it does not. + */ + readonly attribute AString associatedLink; + + /** + * Given the <CODE>CONTEXT_IMAGE</CODE> flag, these methods can be + * used in order to get the image for viewing, saving, or for the clipboard. + * + * @return <CODE>NS_OK</CODE> if successful, otherwise <CODE>NS_ERROR_FAILURE</CODE> if no + * image was found, or NS_ERROR_NULL_POINTER if an internal error occurs where we think there + * is an image, but for some reason it cannot be returned. + */ + + readonly attribute imgIContainer imageContainer; + readonly attribute nsIURI imageSrc; + + /** + * Given the <CODE>CONTEXT_BACKGROUND_IMAGE</CODE> flag, these methods can be + * used in order to get the image for viewing, saving, or for the clipboard. + * + * @return <CODE>NS_OK</CODE> if successful, otherwise <CODE>NS_ERROR_FAILURE</CODE> if no background + * image was found, or NS_ERROR_NULL_POINTER if an internal error occurs where we think there is a + * background image, but for some reason it cannot be returned. + */ + + readonly attribute imgIContainer backgroundImageContainer; + readonly attribute nsIURI backgroundImageSrc; +}; diff --git a/embedding/browser/nsIEmbeddingSiteWindow.idl b/embedding/browser/nsIEmbeddingSiteWindow.idl new file mode 100644 index 000000000..a8eefacb4 --- /dev/null +++ b/embedding/browser/nsIEmbeddingSiteWindow.idl @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +/* THIS IS A PUBLIC EMBEDDING API */ + +/** + * The nsIEmbeddingSiteWindow is implemented by the embedder to provide + * Gecko with the means to call up to the host to resize the window, + * hide or show it and set/get its title. + */ +[scriptable, uuid(0b976267-4aaa-4f36-a2d4-27b5ca8d73bb)] +interface nsIEmbeddingSiteWindow : nsISupports +{ + /** + * Flag indicates that position of the top left corner of the outer area + * is required/specified. + * + * @see setDimensions + * @see getDimensions + */ + const unsigned long DIM_FLAGS_POSITION = 1; + + /** + * Flag indicates that the size of the inner area is required/specified. + * + * @note The inner and outer flags are mutually exclusive and it is + * invalid to combine them. + * + * @see setDimensions + * @see getDimensions + * @see DIM_FLAGS_SIZE_OUTER + */ + const unsigned long DIM_FLAGS_SIZE_INNER = 2; + + /** + * Flag indicates that the size of the outer area is required/specified. + * + * @see setDimensions + * @see getDimensions + * @see DIM_FLAGS_SIZE_INNER + */ + const unsigned long DIM_FLAGS_SIZE_OUTER = 4; + + /** + * Flag indicates that the x parameter should be ignored. + * + * @see setDimensions + */ + const unsigned long DIM_FLAGS_IGNORE_X = 8; + + /** + * Flag indicates that the y parameter should be ignored. + * + * @see setDimensions + */ + const unsigned long DIM_FLAGS_IGNORE_Y = 16; + + /** + * Flag indicates that the cx parameter should be ignored. + * + * @see setDimensions + */ + const unsigned long DIM_FLAGS_IGNORE_CX = 32; + + /** + * Flag indicates that the cy parameter should be ignored. + * + * @see setDimensions + */ + const unsigned long DIM_FLAGS_IGNORE_CY = 64; + + + /** + * Sets the dimensions for the window; the position & size. The + * flags to indicate what the caller wants to set and whether the size + * refers to the inner or outer area. The inner area refers to just + * the embedded area, wheras the outer area can also include any + * surrounding chrome, window frame, title bar, and so on. + * + * @param flags Combination of position, inner and outer size flags. + * The ignore flags are telling the parent to use the + * current values for those dimensions and ignore the + * corresponding parameters the child sends. + * @param x Left hand corner of the outer area. + * @param y Top corner of the outer area. + * @param cx Width of the inner or outer area. + * @param cy Height of the inner or outer area. + * + * @return <code>NS_OK</code> if operation was performed correctly; + * <code>NS_ERROR_UNEXPECTED</code> if window could not be + * destroyed; + * <code>NS_ERROR_INVALID_ARG</code> for bad flag combination + * or illegal dimensions. + * + * @see getDimensions + * @see DIM_FLAGS_POSITION + * @see DIM_FLAGS_SIZE_OUTER + * @see DIM_FLAGS_SIZE_INNER + */ + void setDimensions(in unsigned long flags, in long x, in long y, in long cx, in long cy); + + /** + * Gets the dimensions of the window. The caller may pass + * <CODE>nullptr</CODE> for any value it is uninterested in receiving. + * + * @param flags Combination of position, inner and outer size flag . + * @param x Left hand corner of the outer area; or <CODE>nullptr</CODE>. + * @param y Top corner of the outer area; or <CODE>nullptr</CODE>. + * @param cx Width of the inner or outer area; or <CODE>nullptr</CODE>. + * @param cy Height of the inner or outer area; or <CODE>nullptr</CODE>. + * + * @see setDimensions + * @see DIM_FLAGS_POSITION + * @see DIM_FLAGS_SIZE_OUTER + * @see DIM_FLAGS_SIZE_INNER + */ + void getDimensions(in unsigned long flags, out long x, out long y, out long cx, out long cy); + + /** + * Give the window focus. + */ + void setFocus(); + + /** + * Visibility of the window. + */ + attribute boolean visibility; + + /** + * Title of the window. + */ + attribute wstring title; + + /** + * Native window for the site's window. The implementor should copy the + * native window object into the address supplied by the caller. The + * type of the native window that the address refers to is platform + * and OS specific as follows: + * + * <ul> + * <li>On Win32 it is an <CODE>HWND</CODE>.</li> + * <li>On MacOS this is a <CODE>WindowPtr</CODE>.</li> + * <li>On GTK this is a <CODE>GtkWidget*</CODE>.</li> + * </ul> + */ + [noscript] readonly attribute voidPtr siteWindow; + + /** + * Blur the window. This should unfocus the window and send an onblur event. + */ + void blur(); +}; diff --git a/embedding/browser/nsIPrintPreviewNavigation.idl b/embedding/browser/nsIPrintPreviewNavigation.idl new file mode 100644 index 000000000..87a39ff72 --- /dev/null +++ b/embedding/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/embedding/browser/nsIPrintingPromptService.idl b/embedding/browser/nsIPrintingPromptService.idl new file mode 100644 index 000000000..81d79b57c --- /dev/null +++ b/embedding/browser/nsIPrintingPromptService.idl @@ -0,0 +1,165 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Doc interface here */ + +#include "nsISupports.idl" +#include "nsIWebBrowserPrint.idl" +#include "nsIWebProgressListener.idl" +#include "nsIPrintProgressParams.idl" +#include "nsIPrintSettings.idl" +#include "nsIObserver.idl" + +interface nsIDOMWindow; + +[scriptable, uuid(328daa3e-09e4-455f-bb6f-0a921766042f)] +interface nsIPrintingPromptService : nsISupports +{ + /** + * This service enables embedders to implement their own Print and Progress Dialogs. + * Each platform has a "base" or "basckstop" implementation of the service. The + * service is automatically registered at start up. + * + * Historically, platform toolkits with native dialogs have implemented them in the GFX layer + * Usually they were displayed when a new DeviceContextSpec specific to that platform + * was created. + * + * Windows: The GFX layer no longers supports default toolkit behavior for displaying the + * native Print Dialog. + * If an embedder implemented service returns any error code (other than NS_ERROR_ABORT) + * printing will terminate. + * + * Returning NS_OK assumes that the PrintSettings object was correctly filled in and + * if it does not have valid fields for printer name, etc. it may also terminate. + * + * Defaults for platform service: + * showPrintDialog - displays a native dialog + * showPageSetup - displays a XUL dialog + * showProgress - displays a XUL dialog + * showPrinterProperties - n/a + * + * Summary for Windows Embedders: + * Stated once again: There is no "fallback" native platform support in GFX for the + * displaying of the native print dialog. The current default implementation for Windows + * display a native print dialog but a XUL-based progress dialog. + * If you wish to have a native progress dialog on Windows you will have to create and + * register your own service. + * + * Note: The Windows version Mozilla implements this service which is + * automatically built and registered for you. You can use it as an example. + * It is located at "mozilla/embedding/components/printingui/win". That service + * is capable of displaying a native print dialog and a XUL progress dialog. + * + * To fly your own dialog you may: + * + * 1) Implement this service to display at least the Print Dialog and a Print Progress Dialog + * or you may implement just one of the dialogs and pass back NS_ERROR_NOT_IMPLEMENTED + * for any of the others. + * + * 2) For the Print Dialog: + * You may stub out this service by having all the methods return NS_ERROR_NOT_IMPLEMENTED. + * You can then fly you own dialog and then properly fill in the PrintSettings object + * before calling nsIWebBrowserPrint's Print method. If you stub out this service + * you MUST set "printSilent" to true, if you do not, Printing will terminate and an + * error dialog will be displayed. + * + * Mac: The GFX layer still supports default toolkit behavior for displaying the Print Dialog. + * If an embedder implemented service returns NS_ERROR_NOT_IMPLEMENTED for "showPrintDialog" + * The toolkit will display the native print dialog. + * + * Defaults for platform service: + * Mac OS9: showPrintDialog - displays a native dialog + * showPageSetup - displays a native dialog + * showProgress - displays a XUL dialog + * showPrinterProperties - n/a + * + * Mac OSX: showPrintDialog - displays a native dialog + * showPageSetup - displays a native dialog + * showProgress - not implemented (provided by OS) + * showPrinterProperties - n/a + * + * GTK: There are no native dialog for GTK. + * + * Defaults for platform service: + * showPrintDialog - displays a XUL dialog + * showPageSetup - displays a XUL dialog + * showProgress - displays a XUL dialog + * showPrinterProperties - displays a XUL dialog + * + */ + + + + /** + * Show the Print Dialog + * + * @param parent - a DOM windows the dialog will be parented to (required) + * @param webBrowserPrint - represents the document to be printed (required) + * @param printSettings - PrintSettings for print "job" (required) + * + */ + void showPrintDialog(in mozIDOMWindowProxy parent, + in nsIWebBrowserPrint webBrowserPrint, + in nsIPrintSettings printSettings); + + /** + * Shows the print progress dialog + * + * @param parent - a DOM windows the dialog will be parented to + * @param webBrowserPrint - represents the document to be printed + * @param printSettings - PrintSettings for print "job" + * @param openDialogObserver - an observer that will be notifed when the dialog is opened + * @param isForPrinting - true - for printing, false for print preview + * @param webProgressListener - additional listener can be registered for progress notifications + * @param printProgressParams - parameter object for passing progress state + * @param notifyOnOpen - this indicates that the observer will be notified when the progress + * dialog has been opened. If false is returned it means the observer + * (usually the caller) shouldn't wait + * For Print Preview Progress there is intermediate progress + */ + void showProgress(in mozIDOMWindowProxy parent, + in nsIWebBrowserPrint webBrowserPrint, + in nsIPrintSettings printSettings, + in nsIObserver openDialogObserver, + in boolean isForPrinting, + out nsIWebProgressListener webProgressListener, + out nsIPrintProgressParams printProgressParams, + out boolean notifyOnOpen); + + /** + * Shows the print progress dialog + * + * @param parent - a DOM windows the dialog will be parented to (required) + * @param printSettings - PrintSettings for page setup (required) + * @param aObs - An observer to know if the contents of the Print Settings + * object has changed while the dialog is being shown. + * For example, some platforms may implement an "Apply" button (not required) + */ + void showPageSetup(in mozIDOMWindowProxy parent, + in nsIPrintSettings printSettings, + in nsIObserver aObs); + + /** + * Sometimes platforms need to bring up a special properties dialog for showing + * print specific properties. Although the PrintSettings has a place to set the + * printer name, here is is an argument to be clear as to what printer is being + * asked to have the properties set for it. The Printer name in the PS is ignored. + * + * @param parent - a DOM windows the dialog will be parented to (required) + * @param printerName - name of printer (required) + * @param printSettings - PrintSettings for page setup (required) + */ + void showPrinterProperties(in mozIDOMWindowProxy parent, + in wstring printerName, + in nsIPrintSettings printSettings); + +}; + +%{C++ +// {260FEDC5-524D-4aa6-9A41-E829F4C78B92} +#define NS_PRINTINGPROMPTSERVICE_IID \ + {0x260fedc5, 0x524d, 0x4aa6, { 0x9a, 0x41, 0xe8, 0x29, 0xf4, 0xc7, 0x8b, 0x92}} +%} + diff --git a/embedding/browser/nsITooltipListener.idl b/embedding/browser/nsITooltipListener.idl new file mode 100644 index 000000000..c6e53736f --- /dev/null +++ b/embedding/browser/nsITooltipListener.idl @@ -0,0 +1,44 @@ +/* -*- 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" + +/** + * An optional interface for embedding clients wishing to receive + * notifications for when a tooltip should be displayed or removed. + * The embedder implements this interface on the web browser chrome + * object associated with the window that notifications are required + * for. + * + * @see nsITooltipTextProvider + */ +[scriptable, uuid(44b78386-1dd2-11b2-9ad2-e4eee2ca1916)] +interface nsITooltipListener : nsISupports +{ + /** + * Called when a tooltip should be displayed. + * + * @param aXCoords The tooltip left edge X coordinate. + * @param aYCoords The tooltip top edge Y coordinate. + * @param aTipText The text to display in the tooltip, typically obtained + * from the TITLE attribute of the node (or containing parent) + * over which the pointer has been positioned. + * @param aTipDir The direction (ltr or rtl) in which to display the text + * + * @note + * Coordinates are specified in pixels, relative to the top-left + * corner of the browser area. + * + * @return <code>NS_OK</code> if the tooltip was displayed. + */ + void onShowTooltip(in long aXCoords, in long aYCoords, in wstring aTipText, + in wstring aTipDir); + + /** + * Called when the tooltip should be hidden, either because the pointer + * has moved or the tooltip has timed out. + */ + void onHideTooltip(); +}; diff --git a/embedding/browser/nsITooltipTextProvider.idl b/embedding/browser/nsITooltipTextProvider.idl new file mode 100644 index 000000000..e87344ae0 --- /dev/null +++ b/embedding/browser/nsITooltipTextProvider.idl @@ -0,0 +1,44 @@ +/* -*- Mode: C++; 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 nsIDOMNode; + +/** + * An interface implemented by a tooltip text provider service. This + * service is called to discover what tooltip text is associated + * with the node that the pointer is positioned over. + * + * Embedders may implement and register their own tooltip text provider + * service if they wish to provide different tooltip text. + * + * The default service returns the text stored in the TITLE + * attribute of the node or a containing parent. + * + * @note + * The tooltip text provider service is registered with the contract + * defined in NS_TOOLTIPTEXTPROVIDER_CONTRACTID. + * + * @see nsITooltipListener + * @see nsIComponentManager + * @see nsIDOMNode + */ +[scriptable, uuid(b128a1e6-44f3-4331-8fbe-5af360ff21ee)] +interface nsITooltipTextProvider : nsISupports +{ + /** + * Called to obtain the tooltip text for a node. + * + * @arg aNode The node to obtain the text from. + * @arg aText The tooltip text. + * @arg aDirection The text direction (ltr or rtl) to use + * + * @return <CODE>PR_TRUE</CODE> if tooltip text is associated + * with the node and was returned in the aText argument; + * <CODE>PR_FALSE</CODE> otherwise. + */ + boolean getNodeText(in nsIDOMNode aNode, out wstring aText, out wstring aDirection); +}; diff --git a/embedding/browser/nsIWebBrowser.idl b/embedding/browser/nsIWebBrowser.idl new file mode 100644 index 000000000..e6ff70ae7 --- /dev/null +++ b/embedding/browser/nsIWebBrowser.idl @@ -0,0 +1,163 @@ +/* -*- 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 nsIDOMWindow; +interface mozIDOMWindowProxy; +interface nsIWeakReference; + +%{C++ +namespace mozilla { +class DocShellOriginAttributes; +} +%} + +[ref] native const_OriginAttributesRef(const mozilla::DocShellOriginAttributes); + +/** + * 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, uuid(4052b6da-4faa-4646-b3a1-7e16a01c2dc2)] +interface nsIWebBrowser : nsISupports +{ + /** + * Registers a listener of the type specified by the iid to receive + * callbacks. The browser stores a weak reference to the listener + * to avoid any circular dependencies. + * Typically this method will be called to register an object + * to receive <CODE>nsIWebProgressListener</CODE> or + * <CODE>nsISHistoryListener</CODE> notifications in which case the + * the IID is that of the interface. + * + * @param aListener The listener to be added. + * @param aIID The IID of the interface that will be called + * on the listener as appropriate. + * @return <CODE>NS_OK</CODE> for successful registration; + * <CODE>NS_ERROR_INVALID_ARG</CODE> if aIID is not + * supposed to be registered using this method; + * <CODE>NS_ERROR_FAILURE</CODE> either aListener did not + * expose the interface specified by the IID, or some + * other internal error occurred. + * + * @see removeWebBrowserListener + * @see nsIWeakReference + * @see nsIWebProgressListener + * @see nsISHistoryListener + * + * @return <CODE>NS_OK</CODE>, listener was successfully added; + * <CODE>NS_ERROR_INVALID_ARG</CODE>, one of the arguments was + * invalid or the object did not implement the interface + * specified by the IID. + */ + void addWebBrowserListener(in nsIWeakReference aListener, in nsIIDRef aIID); + + /** + * Removes a previously registered listener. + * + * @param aListener The listener to be removed. + * @param aIID The IID of the interface on the listener that will + * no longer be called. + * + * @return <CODE>NS_OK</CODE>, listener was successfully removed; + * <CODE>NS_ERROR_INVALID_ARG</CODE> arguments was invalid or + * the object did not implement the interface specified by the IID. + * + * @see addWebBrowserListener + * @see nsIWeakReference + */ + void removeWebBrowserListener(in nsIWeakReference aListener, in nsIIDRef aIID); + + /** + * The chrome object associated with the browser instance. The embedder + * must create one chrome object for <I>each</I> 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 <CODE>nsIBaseWindow</CODE> interface. + * + * The chrome object must also implement <CODE>nsIEmbeddingSiteWindow</CODE>. + * + * The chrome may optionally implement <CODE>nsIInterfaceRequestor</CODE>, + * <CODE>nsIWebBrowserChromeFocus</CODE>, + * <CODE>nsIContextMenuListener</CODE> and + * <CODE>nsITooltipListener</CODE> to receive additional notifications + * from the browser object. + * + * The chrome object may optionally implement <CODE>nsIWebProgressListener</CODE> + * instead of explicitly calling <CODE>addWebBrowserListener</CODE> and + * <CODE>removeWebBrowserListener</CODE> to register a progress listener + * object. If the implementation does this, it must also implement + * <CODE>nsIWeakReference</CODE>. + * + * @note The implementation should not refcount the supplied chrome + * object; it should assume that a non <CODE>nullptr</CODE> 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 nsIEmbeddingSiteWindow + * @see nsIInterfaceRequestor + * @see nsIWebBrowserChromeFocus + * @see nsIContextMenuListener + * @see nsITooltipListener + * @see nsIWeakReference + * @see nsIWebProgressListener + */ + attribute nsIWebBrowserChrome containerWindow; + + /** + * URI content listener parent. The embedder may set this property to + * their own implementation if they intend to override or prevent + * how certain kinds of content are loaded. + * + * @note If this attribute is set to an object that implements + * nsISupportsWeakReference, the implementation should get the + * nsIWeakReference and hold that. Otherwise, the implementation + * should not refcount this interface; it should assume that a non + * null value is always valid. In that case, the embedder should + * explicitly set this value back to null if the parent content + * listener is destroyed before the browser object. + * + * @see nsIURIContentListener + */ + attribute nsIURIContentListener parentURIContentListener; + + /** + * The top-level DOM window. The embedder may walk the entire + * DOM starting from this value. + * + * @see nsIDOMWindow + */ + readonly attribute mozIDOMWindowProxy contentDOMWindow; + + /** + * Whether this web browser is active. Active means that it's visible + * enough that we want to avoid certain optimizations like discarding + * decoded image data and throttling the refresh driver. In Firefox, + * this corresponds to the visible tab. + * + * Defaults to true. For optimal performance, set it to false when + * appropriate. + */ + attribute boolean isActive; + + /** + * 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/embedding/browser/nsIWebBrowserChrome.idl b/embedding/browser/nsIWebBrowserChrome.idl new file mode 100644 index 000000000..40f03cbe4 --- /dev/null +++ b/embedding/browser/nsIWebBrowserChrome.idl @@ -0,0 +1,147 @@ +/* -*- 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 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 +{ + const unsigned long STATUS_SCRIPT = 0x00000001; + const unsigned long STATUS_LINK = 0x00000003; + + /** + * Called when the status text in the chrome needs to be updated. + * @param statusType indicates what is setting the text + * @param status status string. null is an acceptable value meaning + * no status. + */ + void setStatus(in unsigned long statusType, in wstring status); + + /** + * The currently loaded WebBrowser. The browser chrome may be + * told to set the WebBrowser object to a new object by setting this + * attribute. In this case the implementer is responsible for taking the + * new WebBrowser object and doing any necessary initialization or setup + * as if it had created the WebBrowser itself. This includes positioning + * setting up listeners etc. + */ + attribute nsIWebBrowser webBrowser; + + /** + * 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; + + // Whether this was opened by nsGlobalWindow::ShowModalDialog. + const unsigned long CHROME_MODAL_CONTENT_WINDOW = 0x00080000; + + // Whether this window should use remote (out-of-process) tabs. + const unsigned long CHROME_REMOTE_WINDOW = 0x00100000; + + // Prevents new window animations on Mac OS X Lion. Ignored on other + // platforms. + const unsigned long CHROME_MAC_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; + + /** + * 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; + + /** + * Asks the implementer to destroy the window associated with this + * WebBrowser object. + */ + void destroyBrowserWindow(); + + /** + * Tells the chrome to size itself such that the browser will be the + * specified size. + * @param aCX new width of the browser + * @param aCY new height of the browser + */ + void sizeBrowserTo(in long aCX, in long aCY); + + /** + * Shows the window as a modal window. + * @return (the function error code) the status value specified by + * in exitModalEventLoop. + */ + void showAsModal(); + + /** + * Is the window modal (that is, currently executing a modal loop)? + * @return true if it's a modal window + */ + boolean isWindowModal(); + + /** + * Exit a modal event loop if we're in one. The implementation + * should also exit out of the loop if the window is destroyed. + * @param aStatus - the result code to return from showAsModal + */ + void exitModalEventLoop(in nsresult aStatus); +}; diff --git a/embedding/browser/nsIWebBrowserChrome2.idl b/embedding/browser/nsIWebBrowserChrome2.idl new file mode 100644 index 000000000..4b479b400 --- /dev/null +++ b/embedding/browser/nsIWebBrowserChrome2.idl @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 "nsIWebBrowserChrome.idl" + +/** + * nsIWebBrowserChrome2 is an extension to nsIWebBrowserChrome. + */ +[scriptable, uuid(2585a7b1-7b47-43c4-bf17-c6bf84e09b7b)] +interface nsIWebBrowserChrome2 : nsIWebBrowserChrome +{ + /** + * Called when the status text in the chrome needs to be updated. This + * method may be called instead of nsIWebBrowserChrome::SetStatus. An + * implementor of this method, should still implement SetStatus. + * + * @param statusType + * Indicates what is setting the text. + * @param status + * Status string. Null is an acceptable value meaning no status. + * @param contextNode + * An object that provides context pertaining to the status type. + * If statusType is STATUS_LINK, then statusContext may be a DOM + * node corresponding to the source of the link. This value can + * be null if there is no context. + */ + void setStatusWithContext(in unsigned long statusType, + in AString statusText, + in nsISupports statusContext); +}; diff --git a/embedding/browser/nsIWebBrowserChrome3.idl b/embedding/browser/nsIWebBrowserChrome3.idl new file mode 100644 index 000000000..a95cab911 --- /dev/null +++ b/embedding/browser/nsIWebBrowserChrome3.idl @@ -0,0 +1,61 @@ +/* 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 "nsIWebBrowserChrome2.idl" +#include "nsIURI.idl" +#include "nsIDOMNode.idl" + +interface nsIDocShell; +interface nsIInputStream; + +/** + * nsIWebBrowserChrome3 is an extension to nsIWebBrowserChrome2. + */ +[scriptable, uuid(542b6625-35a9-426a-8257-c12a345383b0)] +interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2 +{ + /** + * Determines the appropriate target for a link. + * + * @param originalTarget + * The original link target. + * @param linkURI + * Link destination URI. + * @param aDOMNode + * Link DOM node. + * @param isAppTab + * Whether or not the link is in an app tab. + * @returns A new link target, if appropriate. + * Otherwise returns originalTarget. + */ + AString onBeforeLinkTraversal(in AString originalTarget, + in nsIURI linkURI, + in nsIDOMNode linkNode, + in boolean isAppTab); + + /** + * Determines whether a load should continue. + * + * @param aDocShell + * The docshell performing the load. + * @param aURI + * The URI being loaded. + * @param aReferrer + * The referrer of the load. + */ + bool shouldLoadURI(in nsIDocShell aDocShell, + in nsIURI aURI, + in nsIURI aReferrer); + + /** + * Attempts to load the currently loaded page into a fresh process to increase + * available memory. + * + * @param aDocShell + * The docshell performing the load. + */ + bool reloadInFreshProcess(in nsIDocShell aDocShell, + in nsIURI aURI, + in nsIURI aReferrer); +}; diff --git a/embedding/browser/nsIWebBrowserChromeFocus.idl b/embedding/browser/nsIWebBrowserChromeFocus.idl new file mode 100644 index 000000000..8e0b849b9 --- /dev/null +++ b/embedding/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/embedding/browser/nsIWebBrowserFocus.idl b/embedding/browser/nsIWebBrowserFocus.idl new file mode 100644 index 000000000..e2b4a2788 --- /dev/null +++ b/embedding/browser/nsIWebBrowserFocus.idl @@ -0,0 +1,76 @@ +/* -*- 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/. */ + +interface mozIDOMWindowProxy; +interface nsIDOMElement; + +#include "nsISupports.idl" + +/** + * nsIWebBrowserFocus + * Interface that embedders use for controlling and interacting + * with the browser focus management. The embedded browser can be focused by + * clicking in it or tabbing into it. If the browser is currently focused and + * the embedding application's top level window is disabled, deactivate() must + * be called, and activate() called again when the top level window is + * reactivated for the browser's focus memory to work correctly. + */ + +[scriptable, uuid(7f8c754e-5b36-44be-bc96-191b49f08ea6)] +interface nsIWebBrowserFocus : nsISupports +{ + /** + * MANDATORY + * activate() is a mandatory call that must be made to the browser + * when the embedding application's window is activated *and* the + * browser area was the last thing in focus. This method can also be called + * if the embedding application wishes to give the browser area focus, + * without affecting the currently focused element within the browser. + * + * @note + * If you fail to make this call, mozilla focus memory will not work + * correctly. + */ + void activate(); + + /** + * MANDATORY + * deactivate() is a mandatory call that must be made to the browser + * when the embedding application's window is deactivated *and* the + * browser area was the last thing in focus. On non-windows platforms, + * deactivate() should also be called when focus moves from the browser + * to the embedding chrome. + * + * @note + * If you fail to make this call, mozilla focus memory will not work + * correctly. + */ + void deactivate(); + + /** + * Give the first element focus within mozilla + * (i.e. TAB was pressed and focus should enter mozilla) + */ + void setFocusAtFirstElement(); + + /** + * Give the last element focus within mozilla + * (i.e. SHIFT-TAB was pressed and focus should enter mozilla) + */ + void setFocusAtLastElement(); + + /** + * The currently focused nsDOMWindow when the browser is active, + * or the last focused nsDOMWindow when the browser is inactive. + */ + attribute mozIDOMWindowProxy focusedWindow; + + /** + * The currently focused nsDOMElement when the browser is active, + * or the last focused nsDOMElement when the browser is inactive. + */ + attribute nsIDOMElement focusedElement; +}; diff --git a/embedding/browser/nsIWebBrowserPrint.idl b/embedding/browser/nsIWebBrowserPrint.idl new file mode 100644 index 000000000..c5a014e6a --- /dev/null +++ b/embedding/browser/nsIWebBrowserPrint.idl @@ -0,0 +1,152 @@ +/* -*- 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 mozIDOMWindowProxy; +interface nsIPrintSettings; +interface nsIWebProgressListener; + +/** + * 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 + */ + 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 a "global" PrintSettings object + * Creates a new the first time, if one doesn't exist. + * + * Then returns the same object each time after that. + * + * Initializes the globalPrintSettings from the default printer + */ + readonly attribute nsIPrintSettings globalPrintSettings; + + /** + * Returns a pointer to the PrintSettings object that + * that was passed into either "print" or "print preview" + * + * This enables any consumers of the interface to have access + * to the "current" PrintSetting at later points in the execution + */ + readonly attribute nsIPrintSettings currentPrintSettings; + + /** + * Returns a pointer to the current child DOMWindow + * that is being print previewed. (FrameSet Frames) + * + * Returns null if parent document is not a frameset or the entire FrameSet + * document is being print previewed + * + * This enables any consumers of the interface to have access + * to the "current" child DOMWindow at later points in the execution + */ + readonly attribute mozIDOMWindowProxy currentChildDOMWindow; + + /** + * Returns whether it is in Print mode + */ + readonly attribute boolean doingPrint; + + /** + * Returns whether it is in Print Preview mode + */ + readonly attribute boolean doingPrintPreview; + + /** + * This returns whether the current document is a frameset document + */ + readonly attribute boolean isFramesetDocument; + + /** + * This returns whether the current document is a frameset document + */ + readonly attribute boolean isFramesetFrameSelected; + + /** + * This returns whether there is an IFrame selected + */ + readonly attribute boolean isIFrameSelected; + + /** + * This returns whether there is a "range" selection + */ + readonly attribute boolean isRangeSelection; + + /** + * This returns the total number of pages for the Print Preview + */ + readonly attribute long printPreviewNumPages; + + /** + * 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 + */ + void print(in nsIPrintSettings aThePrintSettings, + 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 aChildDOMWin - DOM Window to be print previewed. + * @param aWPListener - is updated during the printpreview + * @return void + */ + void printPreview(in nsIPrintSettings aThePrintSettings, + in mozIDOMWindowProxy aChildDOMWin, + in nsIWebProgressListener aWPListener); + + /** + * Print Preview - Navigates within the window + * + * @param aNavType - navigation enum + * @param aPageNum - page num to navigate to when aNavType = ePrintPreviewGoToPageNum + * @return void + */ + void printPreviewNavigate(in short aNavType, in long aPageNum); + + /** + * Cancels the current print + * @return void + */ + void cancel(); + + /** + * Returns an array of the names of all documents names (Title or URL) + * and sub-documents. This will return a single item if the attr "isFramesetDocument" is false + * and may return any number of items is "isFramesetDocument" is true + * + * @param aCount - returns number of printers returned + * @param aResult - returns array of names + * @return void + */ + void enumerateDocumentNames(out uint32_t aCount,[retval, array, size_is(aCount)] out wstring aResult); + + /** + * This exists PrintPreview mode and returns browser window to galley mode + * @return void + */ + void exitPrintPreview(); + +}; + diff --git a/embedding/browser/nsIWebBrowserSetup.idl b/embedding/browser/nsIWebBrowserSetup.idl new file mode 100644 index 000000000..d30645126 --- /dev/null +++ b/embedding/browser/nsIWebBrowserSetup.idl @@ -0,0 +1,109 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +/** + * The nsIWebBrowserSetup interface lets you set properties on a browser + * object; you can do so at any time during the life cycle of the browser. + * + * @note Unless stated otherwise, settings are presumed to be enabled by + * default. + */ +[scriptable, uuid(F15398A0-8018-11d3-AF70-00A024FFC08C)] +interface nsIWebBrowserSetup : nsISupports +{ + /** + * Boolean. Enables/disables plugin support for this browser. + * + * @see setProperty + */ + const unsigned long SETUP_ALLOW_PLUGINS = 1; + + /** + * Boolean. Enables/disables Javascript support for this browser. + * + * @see setProperty + */ + const unsigned long SETUP_ALLOW_JAVASCRIPT = 2; + + /** + * Boolean. Enables/disables meta redirect support for this browser. + * Meta redirect timers will be ignored if this option is disabled. + * + * @see setProperty + */ + const unsigned long SETUP_ALLOW_META_REDIRECTS = 3; + + /** + * Boolean. Enables/disables subframes within the browser + * + * @see setProperty + */ + const unsigned long SETUP_ALLOW_SUBFRAMES = 4; + + /** + * Boolean. Enables/disables image loading for this browser + * window. If you disable the images, load a page, then enable the images, + * the page will *not* automatically load the images for the previously + * loaded page. This flag controls the state of a webBrowser at load time + * and does not automatically re-load a page when the state is toggled. + * Reloading must be done by hand, or by walking through the DOM tree and + * re-setting the src attributes. + * + * @see setProperty + */ + const unsigned long SETUP_ALLOW_IMAGES = 5; + + /** + * Boolean. Enables/disables whether the document as a whole gets focus before + * traversing the document's content, or after traversing its content. + * + * NOTE: this property is obsolete and now has no effect + * + * @see setProperty + */ + const unsigned long SETUP_FOCUS_DOC_BEFORE_CONTENT = 6; + + /** + * Boolean. Enables/disables the use of global history in the browser. Visited + * URLs will not be recorded in the global history when it is disabled. + * + * @see setProperty + */ + const unsigned long SETUP_USE_GLOBAL_HISTORY = 256; + + /** + * Boolean. A value of PR_TRUE makes the browser a chrome wrapper. + * Default is PR_FALSE. + * + * @since mozilla1.0 + * + * @see setProperty + */ + const unsigned long SETUP_IS_CHROME_WRAPPER = 7; + + + /** + * Boolean. Enables/disables DNS prefetch for HTML anchors in this browser. + * This takes effect starting with the next pageload after the property is + * set. The default is to not allow DNS prefetch, for backwards + * compatibility. + * + * @see setProperty + */ + const unsigned long SETUP_ALLOW_DNS_PREFETCH = 8; + + /** + * Sets an integer or boolean property on the new web browser object. + * Only PR_TRUE and PR_FALSE are legal boolean values. + * + * @param aId The identifier of the property to be set. + * @param aValue The value of the property. + */ + void setProperty(in unsigned long aId, in unsigned long aValue); +}; + diff --git a/embedding/browser/nsIWebBrowserStream.idl b/embedding/browser/nsIWebBrowserStream.idl new file mode 100644 index 000000000..9326b2eaa --- /dev/null +++ b/embedding/browser/nsIWebBrowserStream.idl @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIURI; + +/** + * This interface provides a way to stream data to the web browser. This allows + * loading of data from sources which can not be accessed using URIs and + * nsIWebNavigation. + */ +[scriptable, uuid(86d02f0e-219b-4cfc-9c88-bd98d2cce0b8)] +interface nsIWebBrowserStream : nsISupports +{ + /** + * Prepare to load a stream of data. When this function returns successfully, + * it must be paired by a call to closeStream. + * + * @param aBaseURI + * The base URI of the data. Must not be null. Relative + * URIs will be resolved relative to this URI. + * @param aContentType + * ASCII string giving the content type of the data. If rendering + * content of this type is not supported, this method fails. + * This string may include a charset declaration, for example: + * text/html;charset=ISO-8859-1 + * + * @throw NS_ERROR_NOT_AVAILABLE + * The requested content type is not supported. + * @throw NS_ERROR_IN_PROGRESS + * openStream was called twice without an intermediate closeStream. + */ + void openStream(in nsIURI aBaseURI, in ACString aContentType); + + /** + * Append data to this stream. + * @param aData The data to append + * @param aLen Length of the data to append. + * + * @note To append more than 4 GB of data, call this method multiple times. + */ + void appendToStream([const, array, size_is(aLen)] in octet aData, + in unsigned long aLen); + + /** + * Notifies the browser that all the data has been appended. This may notify + * the user that the browser is "done loading" in some form. + * + * @throw NS_ERROR_UNEXPECTED + * This method was called without a preceding openStream. + */ + void closeStream(); +}; diff --git a/embedding/browser/nsWebBrowser.cpp b/embedding/browser/nsWebBrowser.cpp new file mode 100644 index 000000000..655aa1e43 --- /dev/null +++ b/embedding/browser/nsWebBrowser.cpp @@ -0,0 +1,1952 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Local Includes +#include "nsWebBrowser.h" + +// Helper Classes +#include "nsGfxCIID.h" +#include "nsWidgetsCID.h" + +#include "gfxUtils.h" +#include "mozilla/gfx/2D.h" + +// Interfaces Needed +#include "nsReadableUtils.h" +#include "nsIComponentManager.h" +#include "nsIDOMDocument.h" +#include "nsIDOMWindow.h" +#include "nsIDOMElement.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIWebBrowserChrome.h" +#include "nsPIDOMWindow.h" +#include "nsIWebProgress.h" +#include "nsIWebProgressListener.h" +#include "nsIWebBrowserFocus.h" +#include "nsIWebBrowserStream.h" +#include "nsIPresShell.h" +#include "nsIURIContentListener.h" +#include "nsISHistoryListener.h" +#include "nsIURI.h" +#include "nsIWebBrowserPersist.h" +#include "nsCWebBrowserPersist.h" +#include "nsIServiceManager.h" +#include "nsFocusManager.h" +#include "Layers.h" +#include "gfxContext.h" +#include "nsILoadContext.h" +#include "nsDocShell.h" + +// for painting the background window +#include "mozilla/LookAndFeel.h" + +// Printing Includes +#ifdef NS_PRINTING +#include "nsIWebBrowserPrint.h" +#include "nsIContentViewer.h" +#endif + +// PSM2 includes +#include "nsISecureBrowserUI.h" +#include "nsXULAppAPI.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::layers; + +static NS_DEFINE_CID(kChildCID, NS_CHILD_CID); + +nsWebBrowser::nsWebBrowser() + : mInitInfo(new nsWebBrowserInitInfo()) + , mContentType(typeContentWrapper) + , mActivating(false) + , mShouldEnableHistory(true) + , mIsActive(true) + , mParentNativeWindow(nullptr) + , mProgressListener(nullptr) + , mWidgetListenerDelegate(this) + , mBackgroundColor(0) + , mPersistCurrentState(nsIWebBrowserPersist::PERSIST_STATE_READY) + , mPersistResult(NS_OK) + , mPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_NONE) + , mParentWidget(nullptr) +{ + mWWatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID); + NS_ASSERTION(mWWatch, "failed to get WindowWatcher"); +} + +nsWebBrowser::~nsWebBrowser() +{ + InternalDestroy(); +} + +NS_IMETHODIMP +nsWebBrowser::InternalDestroy() +{ + if (mInternalWidget) { + mInternalWidget->SetWidgetListener(nullptr); + mInternalWidget->Destroy(); + mInternalWidget = nullptr; // Force release here. + } + + SetDocShell(nullptr); + + if (mDocShellTreeOwner) { + mDocShellTreeOwner->WebBrowser(nullptr); + mDocShellTreeOwner = nullptr; + } + + mInitInfo = nullptr; + + mListenerArray = nullptr; + + return NS_OK; +} + +NS_IMPL_ADDREF(nsWebBrowser) +NS_IMPL_RELEASE(nsWebBrowser) + +NS_INTERFACE_MAP_BEGIN(nsWebBrowser) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowser) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowser) + NS_INTERFACE_MAP_ENTRY(nsIWebNavigation) + NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) + NS_INTERFACE_MAP_ENTRY(nsIScrollable) + NS_INTERFACE_MAP_ENTRY(nsITextScroll) + NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem) + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserSetup) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersist) + NS_INTERFACE_MAP_ENTRY(nsICancelable) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserFocus) + NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserStream) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) +NS_INTERFACE_MAP_END + +///***************************************************************************** +// nsWebBrowser::nsIInterfaceRequestor +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetInterface(const nsIID& aIID, void** aSink) +{ + NS_ENSURE_ARG_POINTER(aSink); + + if (NS_SUCCEEDED(QueryInterface(aIID, aSink))) { + return NS_OK; + } + + if (mDocShell) { +#ifdef NS_PRINTING + if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) { + nsCOMPtr<nsIContentViewer> viewer; + mDocShell->GetContentViewer(getter_AddRefs(viewer)); + if (!viewer) { + return NS_NOINTERFACE; + } + + nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint(do_QueryInterface(viewer)); + nsIWebBrowserPrint* print = (nsIWebBrowserPrint*)webBrowserPrint.get(); + NS_ASSERTION(print, "This MUST support this interface!"); + NS_ADDREF(print); + *aSink = print; + return NS_OK; + } +#endif + return mDocShellAsReq->GetInterface(aIID, aSink); + } + + return NS_NOINTERFACE; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebBrowser +//***************************************************************************** + +// listeners that currently support registration through AddWebBrowserListener: +// - nsIWebProgressListener +NS_IMETHODIMP +nsWebBrowser::AddWebBrowserListener(nsIWeakReference* aListener, + const nsIID& aIID) +{ + NS_ENSURE_ARG_POINTER(aListener); + + nsresult rv = NS_OK; + if (!mWebProgress) { + // The window hasn't been created yet, so queue up the listener. They'll be + // registered when the window gets created. + if (!mListenerArray) { + mListenerArray = new nsTArray<nsWebBrowserListenerState>(); + } + + nsWebBrowserListenerState* state = mListenerArray->AppendElement(); + state->mWeakPtr = aListener; + state->mID = aIID; + } else { + nsCOMPtr<nsISupports> supports(do_QueryReferent(aListener)); + if (!supports) { + return NS_ERROR_INVALID_ARG; + } + rv = BindListener(supports, aIID); + } + + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::BindListener(nsISupports* aListener, const nsIID& aIID) +{ + NS_ENSURE_ARG_POINTER(aListener); + NS_ASSERTION(mWebProgress, + "this should only be called after we've retrieved a progress iface"); + nsresult rv = NS_OK; + + // register this listener for the specified interface id + if (aIID.Equals(NS_GET_IID(nsIWebProgressListener))) { + nsCOMPtr<nsIWebProgressListener> listener = do_QueryInterface(aListener, &rv); + if (NS_FAILED(rv)) { + return rv; + } + NS_ENSURE_STATE(mWebProgress); + rv = mWebProgress->AddProgressListener(listener, nsIWebProgress::NOTIFY_ALL); + } else if (aIID.Equals(NS_GET_IID(nsISHistoryListener))) { + nsCOMPtr<nsISHistory> shistory(do_GetInterface(mDocShell, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr<nsISHistoryListener> listener(do_QueryInterface(aListener, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + rv = shistory->AddSHistoryListener(listener); + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::RemoveWebBrowserListener(nsIWeakReference* aListener, + const nsIID& aIID) +{ + NS_ENSURE_ARG_POINTER(aListener); + + nsresult rv = NS_OK; + if (!mWebProgress) { + // if there's no-one to register the listener w/, and we don't have a queue + // going, the the called is calling Remove before an Add which doesn't make + // sense. + if (!mListenerArray) { + return NS_ERROR_FAILURE; + } + + // iterate the array and remove the queued listener + int32_t count = mListenerArray->Length(); + while (count > 0) { + if (mListenerArray->ElementAt(count-1).Equals(aListener, aIID)) { + mListenerArray->RemoveElementAt(count-1); + break; + } + count--; + } + + // if we've emptied the array, get rid of it. + if (0 >= mListenerArray->Length()) { + mListenerArray = nullptr; + } + + } else { + nsCOMPtr<nsISupports> supports(do_QueryReferent(aListener)); + if (!supports) { + return NS_ERROR_INVALID_ARG; + } + rv = UnBindListener(supports, aIID); + } + + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::UnBindListener(nsISupports* aListener, const nsIID& aIID) +{ + NS_ENSURE_ARG_POINTER(aListener); + NS_ASSERTION(mWebProgress, + "this should only be called after we've retrieved a progress iface"); + nsresult rv = NS_OK; + + // remove the listener for the specified interface id + if (aIID.Equals(NS_GET_IID(nsIWebProgressListener))) { + nsCOMPtr<nsIWebProgressListener> listener = do_QueryInterface(aListener, &rv); + if (NS_FAILED(rv)) { + return rv; + } + NS_ENSURE_STATE(mWebProgress); + rv = mWebProgress->RemoveProgressListener(listener); + } else if (aIID.Equals(NS_GET_IID(nsISHistoryListener))) { + nsCOMPtr<nsISHistory> shistory(do_GetInterface(mDocShell, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr<nsISHistoryListener> listener(do_QueryInterface(aListener, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + rv = shistory->RemoveSHistoryListener(listener); + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::EnableGlobalHistory(bool aEnable) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShell->SetUseGlobalHistory(aEnable); +} + +NS_IMETHODIMP +nsWebBrowser::GetContainerWindow(nsIWebBrowserChrome** aTopWindow) +{ + NS_ENSURE_ARG_POINTER(aTopWindow); + + nsCOMPtr<nsIWebBrowserChrome> top; + if (mDocShellTreeOwner) { + top = mDocShellTreeOwner->GetWebBrowserChrome(); + } + + top.forget(aTopWindow); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetContainerWindow(nsIWebBrowserChrome* aTopWindow) +{ + NS_ENSURE_SUCCESS(EnsureDocShellTreeOwner(), NS_ERROR_FAILURE); + return mDocShellTreeOwner->SetWebBrowserChrome(aTopWindow); +} + +NS_IMETHODIMP +nsWebBrowser::GetParentURIContentListener( + nsIURIContentListener** aParentContentListener) +{ + NS_ENSURE_ARG_POINTER(aParentContentListener); + *aParentContentListener = nullptr; + + // get the interface from the docshell + nsCOMPtr<nsIURIContentListener> listener(do_GetInterface(mDocShell)); + + if (listener) { + return listener->GetParentContentListener(aParentContentListener); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetParentURIContentListener( + nsIURIContentListener* aParentContentListener) +{ + // get the interface from the docshell + nsCOMPtr<nsIURIContentListener> listener(do_GetInterface(mDocShell)); + + if (listener) { + return listener->SetParentContentListener(aParentContentListener); + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWebBrowser::GetContentDOMWindow(mozIDOMWindowProxy** aResult) +{ + if (!mDocShell) { + return NS_ERROR_UNEXPECTED; + } + + nsCOMPtr<nsPIDOMWindowOuter> retval = mDocShell->GetWindow(); + retval.forget(aResult); + return *aResult ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWebBrowser::GetIsActive(bool* aResult) +{ + *aResult = mIsActive; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetIsActive(bool aIsActive) +{ + // Set our copy of the value + mIsActive = aIsActive; + + // If we have a docshell, pass on the request + if (mDocShell) { + return mDocShell->SetIsActive(aIsActive); + } + return NS_OK; +} + +void +nsWebBrowser::SetOriginAttributes(const DocShellOriginAttributes& aAttrs) +{ + mOriginAttributes = aAttrs; +} + +//***************************************************************************** +// nsWebBrowser::nsIDocShellTreeItem +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetName(nsAString& aName) +{ + if (mDocShell) { + mDocShell->GetName(aName); + } else { + aName = mInitInfo->name; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetName(const nsAString& aName) +{ + if (mDocShell) { + return mDocShell->SetName(aName); + } else { + mInitInfo->name = aName; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::NameEquals(const nsAString& aName, bool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + if (mDocShell) { + return mDocShell->NameEquals(aName, aResult); + } else { + *aResult = mInitInfo->name.Equals(aName); + } + + return NS_OK; +} + +/* virtual */ int32_t +nsWebBrowser::ItemType() +{ + return mContentType; +} + +NS_IMETHODIMP +nsWebBrowser::GetItemType(int32_t* aItemType) +{ + NS_ENSURE_ARG_POINTER(aItemType); + + *aItemType = ItemType(); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetItemType(int32_t aItemType) +{ + NS_ENSURE_TRUE( + aItemType == typeContentWrapper || aItemType == typeChromeWrapper, + NS_ERROR_FAILURE); + mContentType = aItemType; + if (mDocShell) { + mDocShell->SetItemType(mContentType == typeChromeWrapper ? + static_cast<int32_t>(typeChrome) : + static_cast<int32_t>(typeContent)); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetParent(nsIDocShellTreeItem** aParent) +{ + *aParent = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetSameTypeParent(nsIDocShellTreeItem** aParent) +{ + *aParent = nullptr; + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) +{ + NS_ENSURE_ARG_POINTER(aRootTreeItem); + *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this); + + nsCOMPtr<nsIDocShellTreeItem> parent; + NS_ENSURE_SUCCESS(GetParent(getter_AddRefs(parent)), NS_ERROR_FAILURE); + while (parent) { + *aRootTreeItem = parent; + NS_ENSURE_SUCCESS((*aRootTreeItem)->GetParent(getter_AddRefs(parent)), + NS_ERROR_FAILURE); + } + NS_ADDREF(*aRootTreeItem); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetSameTypeRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) +{ + NS_ENSURE_ARG_POINTER(aRootTreeItem); + *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this); + + nsCOMPtr<nsIDocShellTreeItem> parent; + NS_ENSURE_SUCCESS(GetSameTypeParent(getter_AddRefs(parent)), + NS_ERROR_FAILURE); + while (parent) { + *aRootTreeItem = parent; + NS_ENSURE_SUCCESS((*aRootTreeItem)->GetSameTypeParent(getter_AddRefs(parent)), + NS_ERROR_FAILURE); + } + NS_ADDREF(*aRootTreeItem); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::FindItemWithName(const nsAString& aName, + nsISupports* aRequestor, + nsIDocShellTreeItem* aOriginalRequestor, + nsIDocShellTreeItem** aResult) +{ + NS_ENSURE_STATE(mDocShell); + NS_ASSERTION(mDocShellTreeOwner, + "This should always be set when in this situation"); + + return mDocShell->FindItemWithName( + aName, static_cast<nsIDocShellTreeOwner*>(mDocShellTreeOwner), + aOriginalRequestor, aResult); +} + +nsIDocument* +nsWebBrowser::GetDocument() +{ + return mDocShell ? mDocShell->GetDocument() : nullptr; +} + +nsPIDOMWindowOuter* +nsWebBrowser::GetWindow() +{ + return mDocShell ? mDocShell->GetWindow() : nullptr; +} + +NS_IMETHODIMP +nsWebBrowser::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) +{ + NS_ENSURE_ARG_POINTER(aTreeOwner); + *aTreeOwner = nullptr; + if (mDocShellTreeOwner) { + if (mDocShellTreeOwner->mTreeOwner) { + *aTreeOwner = mDocShellTreeOwner->mTreeOwner; + } else { + *aTreeOwner = mDocShellTreeOwner; + } + } + NS_IF_ADDREF(*aTreeOwner); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) +{ + NS_ENSURE_SUCCESS(EnsureDocShellTreeOwner(), NS_ERROR_FAILURE); + return mDocShellTreeOwner->SetTreeOwner(aTreeOwner); +} + +//***************************************************************************** +// nsWebBrowser::nsIDocShellTreeItem +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetChildCount(int32_t* aChildCount) +{ + NS_ENSURE_ARG_POINTER(aChildCount); + *aChildCount = 0; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::AddChild(nsIDocShellTreeItem* aChild) +{ + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsWebBrowser::RemoveChild(nsIDocShellTreeItem* aChild) +{ + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsWebBrowser::GetChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) +{ + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsWebBrowser::FindChildWithName(const nsAString& aName, + bool aRecurse, + bool aSameType, + nsIDocShellTreeItem* aRequestor, + nsIDocShellTreeItem* aOriginalRequestor, + nsIDocShellTreeItem** aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + + *aResult = nullptr; + return NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebNavigation +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetCanGoBack(bool* aCanGoBack) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetCanGoBack(aCanGoBack); +} + +NS_IMETHODIMP +nsWebBrowser::GetCanGoForward(bool* aCanGoForward) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetCanGoForward(aCanGoForward); +} + +NS_IMETHODIMP +nsWebBrowser::GoBack() +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GoBack(); +} + +NS_IMETHODIMP +nsWebBrowser::GoForward() +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GoForward(); +} + +NS_IMETHODIMP +nsWebBrowser::LoadURIWithOptions(const char16_t* aURI, uint32_t aLoadFlags, + nsIURI* aReferringURI, + uint32_t aReferrerPolicy, + nsIInputStream* aPostDataStream, + nsIInputStream* aExtraHeaderStream, + nsIURI* aBaseURI) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->LoadURIWithOptions( + aURI, aLoadFlags, aReferringURI, aReferrerPolicy, aPostDataStream, + aExtraHeaderStream, aBaseURI); +} + +NS_IMETHODIMP +nsWebBrowser::SetOriginAttributesBeforeLoading(JS::Handle<JS::Value> aOriginAttributes) +{ + return mDocShellAsNav->SetOriginAttributesBeforeLoading(aOriginAttributes); +} + +NS_IMETHODIMP +nsWebBrowser::LoadURI(const char16_t* aURI, uint32_t aLoadFlags, + nsIURI* aReferringURI, + nsIInputStream* aPostDataStream, + nsIInputStream* aExtraHeaderStream) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->LoadURI( + aURI, aLoadFlags, aReferringURI, aPostDataStream, aExtraHeaderStream); +} + +NS_IMETHODIMP +nsWebBrowser::Reload(uint32_t aReloadFlags) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->Reload(aReloadFlags); +} + +NS_IMETHODIMP +nsWebBrowser::GotoIndex(int32_t aIndex) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GotoIndex(aIndex); +} + +NS_IMETHODIMP +nsWebBrowser::Stop(uint32_t aStopFlags) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->Stop(aStopFlags); +} + +NS_IMETHODIMP +nsWebBrowser::GetCurrentURI(nsIURI** aURI) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetCurrentURI(aURI); +} + +NS_IMETHODIMP +nsWebBrowser::GetReferringURI(nsIURI** aURI) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetReferringURI(aURI); +} + +NS_IMETHODIMP +nsWebBrowser::SetSessionHistory(nsISHistory* aSessionHistory) +{ + if (mDocShell) { + return mDocShellAsNav->SetSessionHistory(aSessionHistory); + } else { + mInitInfo->sessionHistory = aSessionHistory; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetSessionHistory(nsISHistory** aSessionHistory) +{ + NS_ENSURE_ARG_POINTER(aSessionHistory); + if (mDocShell) { + return mDocShellAsNav->GetSessionHistory(aSessionHistory); + } else { + *aSessionHistory = mInitInfo->sessionHistory; + } + + NS_IF_ADDREF(*aSessionHistory); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetDocument(nsIDOMDocument** aDocument) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsNav->GetDocument(aDocument); +} + +//***************************************************************************** +// nsWebBrowser::nsIWebBrowserSetup +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::SetProperty(uint32_t aId, uint32_t aValue) +{ + nsresult rv = NS_OK; + + switch (aId) { + case nsIWebBrowserSetup::SETUP_ALLOW_PLUGINS: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowPlugins(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_JAVASCRIPT: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowJavascript(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_META_REDIRECTS: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowMetaRedirects(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_SUBFRAMES: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowSubframes(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_IMAGES: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowImages(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + mDocShell->SetAllowDNSPrefetch(!!aValue); + break; + } + case nsIWebBrowserSetup::SETUP_USE_GLOBAL_HISTORY: { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + rv = EnableGlobalHistory(!!aValue); + mShouldEnableHistory = aValue; + break; + } + case nsIWebBrowserSetup::SETUP_FOCUS_DOC_BEFORE_CONTENT: { + // obsolete + break; + } + case nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER: { + NS_ENSURE_TRUE((aValue == static_cast<uint32_t>(true) || + aValue == static_cast<uint32_t>(false)), + NS_ERROR_INVALID_ARG); + SetItemType(aValue ? static_cast<int32_t>(typeChromeWrapper) : + static_cast<int32_t>(typeContentWrapper)); + break; + } + default: + rv = NS_ERROR_INVALID_ARG; + } + return rv; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebProgressListener +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::OnStateChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + uint32_t aStateFlags, + nsresult aStatus) +{ + if (mPersist) { + mPersist->GetCurrentState(&mPersistCurrentState); + } + if (aStateFlags & STATE_IS_NETWORK && aStateFlags & STATE_STOP) { + mPersist = nullptr; + } + if (mProgressListener) { + return mProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, + aStatus); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::OnProgressChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + int32_t aCurSelfProgress, + int32_t aMaxSelfProgress, + int32_t aCurTotalProgress, + int32_t aMaxTotalProgress) +{ + if (mPersist) { + mPersist->GetCurrentState(&mPersistCurrentState); + } + if (mProgressListener) { + return mProgressListener->OnProgressChange( + aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, + aCurTotalProgress, aMaxTotalProgress); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::OnLocationChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsIURI* aLocation, + uint32_t aFlags) +{ + if (mProgressListener) { + return mProgressListener->OnLocationChange(aWebProgress, aRequest, aLocation, + aFlags); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::OnStatusChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsresult aStatus, + const char16_t* aMessage) +{ + if (mProgressListener) { + return mProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, + aMessage); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::OnSecurityChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + uint32_t aState) +{ + if (mProgressListener) { + return mProgressListener->OnSecurityChange(aWebProgress, aRequest, aState); + } + return NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebBrowserPersist +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetPersistFlags(uint32_t* aPersistFlags) +{ + NS_ENSURE_ARG_POINTER(aPersistFlags); + nsresult rv = NS_OK; + if (mPersist) { + rv = mPersist->GetPersistFlags(&mPersistFlags); + } + *aPersistFlags = mPersistFlags; + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::SetPersistFlags(uint32_t aPersistFlags) +{ + nsresult rv = NS_OK; + mPersistFlags = aPersistFlags; + if (mPersist) { + rv = mPersist->SetPersistFlags(mPersistFlags); + mPersist->GetPersistFlags(&mPersistFlags); + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::GetCurrentState(uint32_t* aCurrentState) +{ + NS_ENSURE_ARG_POINTER(aCurrentState); + if (mPersist) { + mPersist->GetCurrentState(&mPersistCurrentState); + } + *aCurrentState = mPersistCurrentState; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetResult(nsresult* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + if (mPersist) { + mPersist->GetResult(&mPersistResult); + } + *aResult = mPersistResult; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetProgressListener(nsIWebProgressListener** aProgressListener) +{ + NS_ENSURE_ARG_POINTER(aProgressListener); + *aProgressListener = mProgressListener; + NS_IF_ADDREF(*aProgressListener); + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetProgressListener(nsIWebProgressListener* aProgressListener) +{ + mProgressListener = aProgressListener; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SaveURI(nsIURI* aURI, + nsISupports* aCacheKey, + nsIURI* aReferrer, + uint32_t aReferrerPolicy, + nsIInputStream* aPostData, + const char* aExtraHeaders, + nsISupports* aFile, + nsILoadContext* aPrivacyContext) +{ + return SavePrivacyAwareURI( + aURI, aCacheKey, aReferrer, aReferrerPolicy, aPostData, aExtraHeaders, + aFile, aPrivacyContext && aPrivacyContext->UsePrivateBrowsing()); +} + +NS_IMETHODIMP +nsWebBrowser::SavePrivacyAwareURI(nsIURI* aURI, + nsISupports* aCacheKey, + nsIURI* aReferrer, + uint32_t aReferrerPolicy, + nsIInputStream* aPostData, + const char* aExtraHeaders, + nsISupports* aFile, + bool aIsPrivate) +{ + if (mPersist) { + uint32_t currentState; + mPersist->GetCurrentState(¤tState); + if (currentState == PERSIST_STATE_FINISHED) { + mPersist = nullptr; + } else { + // You can't save again until the last save has completed + return NS_ERROR_FAILURE; + } + } + + nsCOMPtr<nsIURI> uri; + if (aURI) { + uri = aURI; + } else { + nsresult rv = GetCurrentURI(getter_AddRefs(uri)); + if (NS_FAILED(rv)) { + return NS_ERROR_FAILURE; + } + } + + // Create a throwaway persistence object to do the work + nsresult rv; + mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + mPersist->SetProgressListener(this); + mPersist->SetPersistFlags(mPersistFlags); + mPersist->GetCurrentState(&mPersistCurrentState); + + rv = mPersist->SavePrivacyAwareURI(uri, aCacheKey, aReferrer, aReferrerPolicy, + aPostData, aExtraHeaders, aFile, aIsPrivate); + if (NS_FAILED(rv)) { + mPersist = nullptr; + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::SaveChannel(nsIChannel* aChannel, nsISupports* aFile) +{ + if (mPersist) { + uint32_t currentState; + mPersist->GetCurrentState(¤tState); + if (currentState == PERSIST_STATE_FINISHED) { + mPersist = nullptr; + } else { + // You can't save again until the last save has completed + return NS_ERROR_FAILURE; + } + } + + // Create a throwaway persistence object to do the work + nsresult rv; + mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + mPersist->SetProgressListener(this); + mPersist->SetPersistFlags(mPersistFlags); + mPersist->GetCurrentState(&mPersistCurrentState); + rv = mPersist->SaveChannel(aChannel, aFile); + if (NS_FAILED(rv)) { + mPersist = nullptr; + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::SaveDocument(nsISupports* aDocumentish, + nsISupports* aFile, + nsISupports* aDataPath, + const char* aOutputContentType, + uint32_t aEncodingFlags, + uint32_t aWrapColumn) +{ + if (mPersist) { + uint32_t currentState; + mPersist->GetCurrentState(¤tState); + if (currentState == PERSIST_STATE_FINISHED) { + mPersist = nullptr; + } else { + // You can't save again until the last save has completed + return NS_ERROR_FAILURE; + } + } + + // Use the specified DOM document, or if none is specified, the one + // attached to the web browser. + + nsCOMPtr<nsISupports> doc; + if (aDocumentish) { + doc = aDocumentish; + } else { + nsCOMPtr<nsIDOMDocument> domDoc; + GetDocument(getter_AddRefs(domDoc)); + doc = domDoc.forget(); + } + if (!doc) { + return NS_ERROR_FAILURE; + } + + // Create a throwaway persistence object to do the work + nsresult rv; + mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + mPersist->SetProgressListener(this); + mPersist->SetPersistFlags(mPersistFlags); + mPersist->GetCurrentState(&mPersistCurrentState); + rv = mPersist->SaveDocument(doc, aFile, aDataPath, aOutputContentType, + aEncodingFlags, aWrapColumn); + if (NS_FAILED(rv)) { + mPersist = nullptr; + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowser::CancelSave() +{ + if (mPersist) { + return mPersist->CancelSave(); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Cancel(nsresult aReason) +{ + if (mPersist) { + return mPersist->Cancel(aReason); + } + return NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIBaseWindow +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::InitWindow(nativeWindow aParentNativeWindow, + nsIWidget* aParentWidget, + int32_t aX, int32_t aY, + int32_t aCX, int32_t aCY) +{ + NS_ENSURE_ARG(aParentNativeWindow || aParentWidget); + NS_ENSURE_STATE(!mDocShell || mInitInfo); + + if (aParentWidget) { + NS_ENSURE_SUCCESS(SetParentWidget(aParentWidget), NS_ERROR_FAILURE); + } else + NS_ENSURE_SUCCESS(SetParentNativeWindow(aParentNativeWindow), + NS_ERROR_FAILURE); + + NS_ENSURE_SUCCESS(SetPositionAndSize(aX, aY, aCX, aCY, 0), + NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Create() +{ + NS_ENSURE_STATE(!mDocShell && (mParentNativeWindow || mParentWidget)); + + nsresult rv = EnsureDocShellTreeOwner(); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIWidget> docShellParentWidget(mParentWidget); + if (!mParentWidget) { + // Create the widget + mInternalWidget = do_CreateInstance(kChildCID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + docShellParentWidget = mInternalWidget; + nsWidgetInitData widgetInit; + + widgetInit.clipChildren = true; + + widgetInit.mWindowType = eWindowType_child; + LayoutDeviceIntRect bounds(mInitInfo->x, mInitInfo->y, + mInitInfo->cx, mInitInfo->cy); + + mInternalWidget->SetWidgetListener(&mWidgetListenerDelegate); + rv = mInternalWidget->Create(nullptr, mParentNativeWindow, bounds, + &widgetInit); + NS_ENSURE_SUCCESS(rv, rv); + } + + nsCOMPtr<nsIDocShell> docShell( + do_CreateInstance("@mozilla.org/docshell;1", &rv)); + NS_ENSURE_SUCCESS(rv, rv); + nsDocShell::Cast(docShell)->SetOriginAttributes(mOriginAttributes); + rv = SetDocShell(docShell); + NS_ENSURE_SUCCESS(rv, rv); + + // get the system default window background colour + LookAndFeel::GetColor(LookAndFeel::eColorID_WindowBackground, + &mBackgroundColor); + + // the docshell has been set so we now have our listener registrars. + if (mListenerArray) { + // we had queued up some listeners, let's register them now. + uint32_t count = mListenerArray->Length(); + uint32_t i = 0; + NS_ASSERTION(count > 0, "array construction problem"); + while (i < count) { + nsWebBrowserListenerState& state = mListenerArray->ElementAt(i); + nsCOMPtr<nsISupports> listener = do_QueryReferent(state.mWeakPtr); + NS_ASSERTION(listener, "bad listener"); + (void)BindListener(listener, state.mID); + i++; + } + mListenerArray = nullptr; + } + + // HACK ALERT - this registration registers the nsDocShellTreeOwner as a + // nsIWebBrowserListener so it can setup its MouseListener in one of the + // progress callbacks. If we can register the MouseListener another way, this + // registration can go away, and nsDocShellTreeOwner can stop implementing + // nsIWebProgressListener. + nsCOMPtr<nsISupports> supports = nullptr; + (void)mDocShellTreeOwner->QueryInterface( + NS_GET_IID(nsIWebProgressListener), + static_cast<void**>(getter_AddRefs(supports))); + (void)BindListener(supports, NS_GET_IID(nsIWebProgressListener)); + + NS_ENSURE_SUCCESS(mDocShellAsWin->InitWindow(nullptr, docShellParentWidget, + mInitInfo->x, mInitInfo->y, + mInitInfo->cx, mInitInfo->cy), + NS_ERROR_FAILURE); + + mDocShell->SetName(mInitInfo->name); + if (mContentType == typeChromeWrapper) { + mDocShell->SetItemType(nsIDocShellTreeItem::typeChrome); + } else { + mDocShell->SetItemType(nsIDocShellTreeItem::typeContent); + } + mDocShell->SetTreeOwner(mDocShellTreeOwner); + + // If the webbrowser is a content docshell item then we won't hear any + // events from subframes. To solve that we install our own chrome event + // handler that always gets called (even for subframes) for any bubbling + // event. + + if (!mInitInfo->sessionHistory) { + mInitInfo->sessionHistory = do_CreateInstance(NS_SHISTORY_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + } + mDocShellAsNav->SetSessionHistory(mInitInfo->sessionHistory); + + if (XRE_IsParentProcess()) { + // Hook up global history. Do not fail if we can't - just warn. + rv = EnableGlobalHistory(mShouldEnableHistory); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "EnableGlobalHistory() failed"); + } + + NS_ENSURE_SUCCESS(mDocShellAsWin->Create(), NS_ERROR_FAILURE); + + // Hook into the OnSecurityChange() notification for lock/unlock icon + // updates + nsCOMPtr<mozIDOMWindowProxy> domWindow; + rv = GetContentDOMWindow(getter_AddRefs(domWindow)); + if (NS_SUCCEEDED(rv)) { + // this works because the implementation of nsISecureBrowserUI + // (nsSecureBrowserUIImpl) gets a docShell from the domWindow, + // and calls docShell->SetSecurityUI(this); + nsCOMPtr<nsISecureBrowserUI> securityUI = + do_CreateInstance(NS_SECURE_BROWSER_UI_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) { + securityUI->Init(domWindow); + } + } + + mDocShellTreeOwner->AddToWatcher(); // evil twin of Remove in SetDocShell(0) + mDocShellTreeOwner->AddChromeListeners(); + + mInitInfo = nullptr; + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Destroy() +{ + InternalDestroy(); + + if (!mInitInfo) { + mInitInfo = new nsWebBrowserInitInfo(); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetUnscaledDevicePixelsPerCSSPixel(double* aScale) +{ + *aScale = mParentWidget ? mParentWidget->GetDefaultScale().scale : 1.0; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetDevicePixelsPerDesktopPixel(double* aScale) +{ + *aScale = mParentWidget ? mParentWidget->GetDesktopToDeviceScale().scale + : 1.0; + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetPositionDesktopPix(int32_t aX, int32_t aY) +{ + // XXX jfkthame + // It's not clear to me whether this will be fully correct across + // potential multi-screen, mixed-DPI configurations for all platforms; + // we might need to add code paths that make it possible to pass the + // desktop-pix parameters all the way through to the native widget, + // to avoid the risk of device-pixel coords mapping to the wrong + // display on OS X with mixed retina/non-retina screens. + double scale = 1.0; + GetDevicePixelsPerDesktopPixel(&scale); + return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale)); +} + +NS_IMETHODIMP +nsWebBrowser::SetPosition(int32_t aX, int32_t aY) +{ + int32_t cx = 0; + int32_t cy = 0; + + GetSize(&cx, &cy); + + return SetPositionAndSize(aX, aY, cx, cy, 0); +} + +NS_IMETHODIMP +nsWebBrowser::GetPosition(int32_t* aX, int32_t* aY) +{ + return GetPositionAndSize(aX, aY, nullptr, nullptr); +} + +NS_IMETHODIMP +nsWebBrowser::SetSize(int32_t aCX, int32_t aCY, bool aRepaint) +{ + int32_t x = 0; + int32_t y = 0; + + GetPosition(&x, &y); + + return SetPositionAndSize(x, y, aCX, aCY, + aRepaint ? nsIBaseWindow::eRepaint : 0); +} + +NS_IMETHODIMP +nsWebBrowser::GetSize(int32_t* aCX, int32_t* aCY) +{ + return GetPositionAndSize(nullptr, nullptr, aCX, aCY); +} + +NS_IMETHODIMP +nsWebBrowser::SetPositionAndSize(int32_t aX, int32_t aY, + int32_t aCX, int32_t aCY, uint32_t aFlags) +{ + if (!mDocShell) { + mInitInfo->x = aX; + mInitInfo->y = aY; + mInitInfo->cx = aCX; + mInitInfo->cy = aCY; + } else { + int32_t doc_x = aX; + int32_t doc_y = aY; + + // If there is an internal widget we need to make the docShell coordinates + // relative to the internal widget rather than the calling app's parent. + // We also need to resize our widget then. + if (mInternalWidget) { + doc_x = doc_y = 0; + NS_ENSURE_SUCCESS(mInternalWidget->Resize(aX, aY, aCX, aCY, + !!(aFlags & nsIBaseWindow::eRepaint)), + NS_ERROR_FAILURE); + } + // Now reposition/ resize the doc + NS_ENSURE_SUCCESS( + mDocShellAsWin->SetPositionAndSize(doc_x, doc_y, aCX, aCY, aFlags), + NS_ERROR_FAILURE); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetPositionAndSize(int32_t* aX, int32_t* aY, + int32_t* aCX, int32_t* aCY) +{ + if (!mDocShell) { + if (aX) { + *aX = mInitInfo->x; + } + if (aY) { + *aY = mInitInfo->y; + } + if (aCX) { + *aCX = mInitInfo->cx; + } + if (aCY) { + *aCY = mInitInfo->cy; + } + } else if (mInternalWidget) { + LayoutDeviceIntRect bounds = mInternalWidget->GetBounds(); + + if (aX) { + *aX = bounds.x; + } + if (aY) { + *aY = bounds.y; + } + if (aCX) { + *aCX = bounds.width; + } + if (aCY) { + *aCY = bounds.height; + } + return NS_OK; + } else { + // Can directly return this as it is the + // same interface, thus same returns. + return mDocShellAsWin->GetPositionAndSize(aX, aY, aCX, aCY); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Repaint(bool aForce) +{ + NS_ENSURE_STATE(mDocShell); + // Can directly return this as it is the + // same interface, thus same returns. + return mDocShellAsWin->Repaint(aForce); +} + +NS_IMETHODIMP +nsWebBrowser::GetParentWidget(nsIWidget** aParentWidget) +{ + NS_ENSURE_ARG_POINTER(aParentWidget); + + *aParentWidget = mParentWidget; + + NS_IF_ADDREF(*aParentWidget); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetParentWidget(nsIWidget* aParentWidget) +{ + NS_ENSURE_STATE(!mDocShell); + + mParentWidget = aParentWidget; + if (mParentWidget) { + mParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET); + } else { + mParentNativeWindow = nullptr; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetParentNativeWindow(nativeWindow* aParentNativeWindow) +{ + NS_ENSURE_ARG_POINTER(aParentNativeWindow); + + *aParentNativeWindow = mParentNativeWindow; + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetParentNativeWindow(nativeWindow aParentNativeWindow) +{ + NS_ENSURE_STATE(!mDocShell); + + mParentNativeWindow = aParentNativeWindow; + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetNativeHandle(nsAString& aNativeHandle) +{ + // the nativeHandle should be accessed from nsIXULWindow + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsWebBrowser::GetVisibility(bool* aVisibility) +{ + NS_ENSURE_ARG_POINTER(aVisibility); + + if (!mDocShell) { + *aVisibility = mInitInfo->visible; + } else { + NS_ENSURE_SUCCESS(mDocShellAsWin->GetVisibility(aVisibility), + NS_ERROR_FAILURE); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetVisibility(bool aVisibility) +{ + if (!mDocShell) { + mInitInfo->visible = aVisibility; + } else { + NS_ENSURE_SUCCESS(mDocShellAsWin->SetVisibility(aVisibility), + NS_ERROR_FAILURE); + if (mInternalWidget) { + mInternalWidget->Show(aVisibility); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetEnabled(bool* aEnabled) +{ + if (mInternalWidget) { + *aEnabled = mInternalWidget->IsEnabled(); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWebBrowser::SetEnabled(bool aEnabled) +{ + if (mInternalWidget) { + return mInternalWidget->Enable(aEnabled); + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWebBrowser::GetMainWidget(nsIWidget** aMainWidget) +{ + NS_ENSURE_ARG_POINTER(aMainWidget); + + if (mInternalWidget) { + *aMainWidget = mInternalWidget; + } else { + *aMainWidget = mParentWidget; + } + + NS_IF_ADDREF(*aMainWidget); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocus() +{ + nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow(); + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); + + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return fm ? fm->SetFocusedWindow(window) : NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetTitle(char16_t** aTitle) +{ + NS_ENSURE_ARG_POINTER(aTitle); + NS_ENSURE_STATE(mDocShell); + + NS_ENSURE_SUCCESS(mDocShellAsWin->GetTitle(aTitle), NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetTitle(const char16_t* aTitle) +{ + NS_ENSURE_STATE(mDocShell); + + NS_ENSURE_SUCCESS(mDocShellAsWin->SetTitle(aTitle), NS_ERROR_FAILURE); + + return NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIScrollable +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::GetDefaultScrollbarPreferences(int32_t aScrollOrientation, + int32_t* aScrollbarPref) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsScrollable->GetDefaultScrollbarPreferences( + aScrollOrientation, aScrollbarPref); +} + +NS_IMETHODIMP +nsWebBrowser::SetDefaultScrollbarPreferences(int32_t aScrollOrientation, + int32_t aScrollbarPref) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsScrollable->SetDefaultScrollbarPreferences( + aScrollOrientation, aScrollbarPref); +} + +NS_IMETHODIMP +nsWebBrowser::GetScrollbarVisibility(bool* aVerticalVisible, + bool* aHorizontalVisible) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsScrollable->GetScrollbarVisibility(aVerticalVisible, + aHorizontalVisible); +} + +//***************************************************************************** +// nsWebBrowser::nsITextScroll +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::ScrollByLines(int32_t aNumLines) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsTextScroll->ScrollByLines(aNumLines); +} + +NS_IMETHODIMP +nsWebBrowser::ScrollByPages(int32_t aNumPages) +{ + NS_ENSURE_STATE(mDocShell); + + return mDocShellAsTextScroll->ScrollByPages(aNumPages); +} + +//***************************************************************************** +// nsWebBrowser: Listener Helpers +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::SetDocShell(nsIDocShell* aDocShell) +{ + // We need to keep the docshell alive while we perform the changes, but we + // don't need to call any methods on it. + nsCOMPtr<nsIDocShell> kungFuDeathGrip(mDocShell); + mozilla::Unused << kungFuDeathGrip; + + if (aDocShell) { + NS_ENSURE_TRUE(!mDocShell, NS_ERROR_FAILURE); + + nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(aDocShell)); + nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(aDocShell)); + nsCOMPtr<nsIWebNavigation> nav(do_QueryInterface(aDocShell)); + nsCOMPtr<nsIScrollable> scrollable(do_QueryInterface(aDocShell)); + nsCOMPtr<nsITextScroll> textScroll(do_QueryInterface(aDocShell)); + nsCOMPtr<nsIWebProgress> progress(do_GetInterface(aDocShell)); + NS_ENSURE_TRUE(req && baseWin && nav && scrollable && textScroll && progress, + NS_ERROR_FAILURE); + + mDocShell = aDocShell; + mDocShellAsReq = req; + mDocShellAsWin = baseWin; + mDocShellAsNav = nav; + mDocShellAsScrollable = scrollable; + mDocShellAsTextScroll = textScroll; + mWebProgress = progress; + + // By default, do not allow DNS prefetch, so we don't break our frozen + // API. Embeddors who decide to enable it should do so manually. + mDocShell->SetAllowDNSPrefetch(false); + + // It's possible to call setIsActive() on us before we have a docshell. + // If we're getting a docshell now, pass along our desired value. The + // default here (true) matches the default of the docshell, so this is + // a no-op unless setIsActive(false) has been called on us. + mDocShell->SetIsActive(mIsActive); + } else { + if (mDocShellTreeOwner) { + mDocShellTreeOwner->RemoveFromWatcher(); // evil twin of Add in Create() + } + if (mDocShellAsWin) { + mDocShellAsWin->Destroy(); + } + + mDocShell = nullptr; + mDocShellAsReq = nullptr; + mDocShellAsWin = nullptr; + mDocShellAsNav = nullptr; + mDocShellAsScrollable = nullptr; + mDocShellAsTextScroll = nullptr; + mWebProgress = nullptr; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::EnsureDocShellTreeOwner() +{ + if (mDocShellTreeOwner) { + return NS_OK; + } + + mDocShellTreeOwner = new nsDocShellTreeOwner(); + mDocShellTreeOwner->WebBrowser(this); + + return NS_OK; +} + +static void +DrawPaintedLayer(PaintedLayer* aLayer, + gfxContext* aContext, + const nsIntRegion& aRegionToDraw, + const nsIntRegion& aDirtyRegion, + DrawRegionClip aClip, + const nsIntRegion& aRegionToInvalidate, + void* aCallbackData) +{ + DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); + + ColorPattern color(ToDeviceColor(*static_cast<nscolor*>(aCallbackData))); + nsIntRect dirtyRect = aRegionToDraw.GetBounds(); + aDrawTarget.FillRect( + Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height), color); +} + +void +nsWebBrowser::WindowRaised(nsIWidget* aWidget) +{ +#if defined(DEBUG_smaug) + nsCOMPtr<nsIDocument> document = mDocShell->GetDocument(); + nsAutoString documentURI; + document->GetDocumentURI(documentURI); + printf("nsWebBrowser::NS_ACTIVATE %p %s\n", (void*)this, + NS_ConvertUTF16toUTF8(documentURI).get()); +#endif + Activate(); +} + +void +nsWebBrowser::WindowLowered(nsIWidget* aWidget) +{ +#if defined(DEBUG_smaug) + nsCOMPtr<nsIDocument> document = mDocShell->GetDocument(); + nsAutoString documentURI; + document->GetDocumentURI(documentURI); + printf("nsWebBrowser::NS_DEACTIVATE %p %s\n", (void*)this, + NS_ConvertUTF16toUTF8(documentURI).get()); +#endif + Deactivate(); +} + +bool +nsWebBrowser::PaintWindow(nsIWidget* aWidget, LayoutDeviceIntRegion aRegion) +{ + LayerManager* layerManager = aWidget->GetLayerManager(); + NS_ASSERTION(layerManager, "Must be in paint event"); + + layerManager->BeginTransaction(); + RefPtr<PaintedLayer> root = layerManager->CreatePaintedLayer(); + if (root) { + nsIntRect dirtyRect = aRegion.GetBounds().ToUnknownRect(); + root->SetVisibleRegion(LayerIntRegion::FromUnknownRegion(dirtyRect)); + layerManager->SetRoot(root); + } + + layerManager->EndTransaction(DrawPaintedLayer, &mBackgroundColor); + return true; +} +/* +NS_IMETHODIMP +nsWebBrowser::GetPrimaryContentWindow(mozIDOMWindowProxy** aDOMWindow) +{ + *aDOMWindow = nullptr; + + nsCOMPtr<nsIDocShellTreeItem> item; + NS_ENSURE_TRUE(mDocShellTreeOwner, NS_ERROR_FAILURE); + mDocShellTreeOwner->GetPrimaryContentShell(getter_AddRefs(item)); + NS_ENSURE_TRUE(item, NS_ERROR_FAILURE); + + nsCOMPtr<nsIDocShell> docShell; + docShell = do_QueryInterface(item); + NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); + + nsCOMPtr<nsPIDOMWindowOuter> domWindow = docShell->GetWindow(); + NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE); + + *aDOMWindow = domWindow; + NS_ADDREF(*aDOMWindow); + return NS_OK; +} +*/ +//***************************************************************************** +// nsWebBrowser::nsIWebBrowserFocus +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::Activate(void) +{ + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow(); + if (fm && window) { + return fm->WindowRaised(window); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::Deactivate(void) +{ + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow(); + if (fm && window) { + return fm->WindowLowered(window); + } + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocusAtFirstElement(void) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocusAtLastElement(void) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetFocusedWindow(mozIDOMWindowProxy** aFocusedWindow) +{ + NS_ENSURE_ARG_POINTER(aFocusedWindow); + *aFocusedWindow = nullptr; + + NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + + nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell->GetWindow(); + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); + + nsCOMPtr<nsIDOMElement> focusedElement; + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return fm ? fm->GetFocusedElementForWindow(window, true, aFocusedWindow, + getter_AddRefs(focusedElement)) : + NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocusedWindow(mozIDOMWindowProxy* aFocusedWindow) +{ + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return fm ? fm->SetFocusedWindow(aFocusedWindow) : NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::GetFocusedElement(nsIDOMElement** aFocusedElement) +{ + NS_ENSURE_ARG_POINTER(aFocusedElement); + NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + + nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell->GetWindow(); + NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); + + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return + fm ? fm->GetFocusedElementForWindow(window, true, nullptr, aFocusedElement) : + NS_OK; +} + +NS_IMETHODIMP +nsWebBrowser::SetFocusedElement(nsIDOMElement* aFocusedElement) +{ + nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID); + return fm ? fm->SetFocus(aFocusedElement, 0) : NS_OK; +} + +//***************************************************************************** +// nsWebBrowser::nsIWebBrowserStream +//***************************************************************************** + +NS_IMETHODIMP +nsWebBrowser::OpenStream(nsIURI* aBaseURI, const nsACString& aContentType) +{ + nsresult rv; + + if (!mStream) { + mStream = new nsEmbedStream(); + mStream->InitOwner(this); + rv = mStream->Init(); + if (NS_FAILED(rv)) { + return rv; + } + } + + return mStream->OpenStream(aBaseURI, aContentType); +} + + +NS_IMETHODIMP +nsWebBrowser::AppendToStream(const uint8_t* aData, uint32_t aLen) +{ + if (!mStream) { + return NS_ERROR_FAILURE; + } + + return mStream->AppendToStream(aData, aLen); +} + +NS_IMETHODIMP +nsWebBrowser::CloseStream() +{ + nsresult rv; + + if (!mStream) { + return NS_ERROR_FAILURE; + } + rv = mStream->CloseStream(); + + mStream = nullptr; + + return rv; +} + +bool +nsWebBrowser::WidgetListenerDelegate::PaintWindow( + nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) +{ + RefPtr<nsWebBrowser> holder = mWebBrowser; + return holder->PaintWindow(aWidget, aRegion); +} diff --git a/embedding/browser/nsWebBrowser.h b/embedding/browser/nsWebBrowser.h new file mode 100644 index 000000000..80c106cb9 --- /dev/null +++ b/embedding/browser/nsWebBrowser.h @@ -0,0 +1,185 @@ +/* -*- 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 "nsAutoPtr.h" +#include "nsCOMPtr.h" + +// Interfaces needed +#include "nsCWebBrowser.h" +#include "nsIBaseWindow.h" +#include "nsIDocShell.h" +#include "nsIDocShellTreeItem.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIScrollable.h" +#include "nsISHistory.h" +#include "nsITextScroll.h" +#include "nsIWidget.h" +#include "nsIWebProgress.h" +#include "nsISecureBrowserUI.h" +#include "nsIWebBrowser.h" +#include "nsIWebNavigation.h" +#include "nsIWebBrowserSetup.h" +#include "nsIWebBrowserPersist.h" +#include "nsIWebBrowserFocus.h" +#include "nsIWebBrowserStream.h" +#include "nsIWindowWatcher.h" +#include "nsIPrintSettings.h" +#include "nsEmbedStream.h" +#include "nsIWidgetListener.h" + +#include "mozilla/BasePrincipal.h" +#include "nsTArray.h" +#include "nsWeakPtr.h" + +class nsWebBrowserInitInfo +{ +public: + // nsIBaseWindow Stuff + int32_t x; + int32_t y; + int32_t cx; + int32_t cy; + bool visible; + nsCOMPtr<nsISHistory> sessionHistory; + nsString name; +}; + +class nsWebBrowserListenerState +{ +public: + bool Equals(nsIWeakReference* aListener, const nsIID& aID) + { + return mWeakPtr.get() == aListener && mID.Equals(aID); + } + + nsWeakPtr mWeakPtr; + nsIID mID; +}; + +// {cda5863a-aa9c-411e-be49-ea0d525ab4b5} - +#define NS_WEBBROWSER_CID \ + { 0xcda5863a, 0xaa9c, 0x411e, { 0xbe, 0x49, 0xea, 0x0d, 0x52, 0x5a, 0xb4, 0xb5 } } + + +class nsWebBrowser final : public nsIWebBrowser, + public nsIWebNavigation, + public nsIWebBrowserSetup, + public nsIDocShellTreeItem, + public nsIBaseWindow, + public nsIScrollable, + public nsITextScroll, + public nsIInterfaceRequestor, + public nsIWebBrowserPersist, + public nsIWebBrowserFocus, + public nsIWebProgressListener, + public nsIWebBrowserStream, + public nsSupportsWeakReference +{ + friend class nsDocShellTreeOwner; + +public: + + // The implementation of non-refcounted nsIWidgetListener, which would hold a + // strong reference on stack before calling nsWebBrowser. + class WidgetListenerDelegate : public nsIWidgetListener + { + public: + explicit WidgetListenerDelegate(nsWebBrowser* aWebBrowser) + : mWebBrowser(aWebBrowser) {} + 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; + }; + + nsWebBrowser(); + + NS_DECL_ISUPPORTS + + NS_DECL_NSIBASEWINDOW + NS_DECL_NSIDOCSHELLTREEITEM + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSISCROLLABLE + NS_DECL_NSITEXTSCROLL + NS_DECL_NSIWEBBROWSER + NS_DECL_NSIWEBNAVIGATION + NS_DECL_NSIWEBBROWSERSETUP + NS_DECL_NSIWEBBROWSERPERSIST + NS_DECL_NSICANCELABLE + NS_DECL_NSIWEBBROWSERFOCUS + NS_DECL_NSIWEBBROWSERSTREAM + NS_DECL_NSIWEBPROGRESSLISTENER + +protected: + virtual ~nsWebBrowser(); + NS_IMETHOD InternalDestroy(); + + // XXXbz why are these NS_IMETHOD? They're not interface methods! + NS_IMETHOD SetDocShell(nsIDocShell* aDocShell); + NS_IMETHOD EnsureDocShellTreeOwner(); + NS_IMETHOD BindListener(nsISupports* aListener, const nsIID& aIID); + NS_IMETHOD UnBindListener(nsISupports* aListener, const nsIID& aIID); + NS_IMETHOD EnableGlobalHistory(bool aEnable); + + // nsIWidgetListener + virtual void WindowRaised(nsIWidget* aWidget); + virtual void WindowLowered(nsIWidget* aWidget); + bool PaintWindow(nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion); + +protected: + RefPtr<nsDocShellTreeOwner> mDocShellTreeOwner; + nsCOMPtr<nsIDocShell> mDocShell; + nsCOMPtr<nsIInterfaceRequestor> mDocShellAsReq; + nsCOMPtr<nsIBaseWindow> mDocShellAsWin; + nsCOMPtr<nsIWebNavigation> mDocShellAsNav; + nsCOMPtr<nsIScrollable> mDocShellAsScrollable; + nsCOMPtr<nsITextScroll> mDocShellAsTextScroll; + mozilla::DocShellOriginAttributes mOriginAttributes; + + nsCOMPtr<nsIWidget> mInternalWidget; + nsCOMPtr<nsIWindowWatcher> mWWatch; + nsAutoPtr<nsWebBrowserInitInfo> mInitInfo; + uint32_t mContentType; + bool mActivating; + bool mShouldEnableHistory; + bool mIsActive; + nativeWindow mParentNativeWindow; + nsIWebProgressListener* mProgressListener; + nsCOMPtr<nsIWebProgress> mWebProgress; + + nsCOMPtr<nsIPrintSettings> mPrintSettings; + + WidgetListenerDelegate mWidgetListenerDelegate; + + // cached background color + nscolor mBackgroundColor; + + // persistence object + nsCOMPtr<nsIWebBrowserPersist> mPersist; + uint32_t mPersistCurrentState; + nsresult mPersistResult; + uint32_t mPersistFlags; + + // stream + RefPtr<nsEmbedStream> mStream; + + // Weak Reference interfaces... + nsIWidget* mParentWidget; + nsAutoPtr<nsTArray<nsWebBrowserListenerState> > mListenerArray; +}; + +#endif /* nsWebBrowser_h__ */ diff --git a/embedding/browser/nsWebBrowserContentPolicy.cpp b/embedding/browser/nsWebBrowserContentPolicy.cpp new file mode 100644 index 000000000..f6b17a197 --- /dev/null +++ b/embedding/browser/nsWebBrowserContentPolicy.cpp @@ -0,0 +1,108 @@ +/* -*- 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 "nsIContentViewer.h" + +nsWebBrowserContentPolicy::nsWebBrowserContentPolicy() +{ + MOZ_COUNT_CTOR(nsWebBrowserContentPolicy); +} + +nsWebBrowserContentPolicy::~nsWebBrowserContentPolicy() +{ + MOZ_COUNT_DTOR(nsWebBrowserContentPolicy); +} + +NS_IMPL_ISUPPORTS(nsWebBrowserContentPolicy, nsIContentPolicy) + +NS_IMETHODIMP +nsWebBrowserContentPolicy::ShouldLoad(uint32_t aContentType, + nsIURI* aContentLocation, + nsIURI* aRequestingLocation, + nsISupports* aRequestingContext, + const nsACString& aMimeGuess, + nsISupports* aExtra, + nsIPrincipal* aRequestPrincipal, + int16_t* aShouldLoad) +{ + NS_PRECONDITION(aShouldLoad, "Null out param"); + + MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), + "We should only see external content policy types here."); + + *aShouldLoad = nsIContentPolicy::ACCEPT; + + nsIDocShell* shell = NS_CP_GetDocShellFromContext(aRequestingContext); + /* We're going to dereference shell, so make sure it isn't null */ + if (!shell) { + return NS_OK; + } + + nsresult rv; + bool allowed = true; + + switch (aContentType) { + case nsIContentPolicy::TYPE_SCRIPT: + rv = shell->GetAllowJavascript(&allowed); + break; + case nsIContentPolicy::TYPE_SUBDOCUMENT: + rv = shell->GetAllowSubframes(&allowed); + break; +#if 0 + /* XXXtw: commented out in old code; add during conpol phase 2 */ + case nsIContentPolicy::TYPE_REFRESH: + rv = shell->GetAllowMetaRedirects(&allowed); /* meta _refresh_ */ + break; +#endif + case nsIContentPolicy::TYPE_IMAGE: + case nsIContentPolicy::TYPE_IMAGESET: + rv = shell->GetAllowImages(&allowed); + break; + default: + return NS_OK; + } + + if (NS_SUCCEEDED(rv) && !allowed) { + *aShouldLoad = nsIContentPolicy::REJECT_TYPE; + } + return rv; +} + +NS_IMETHODIMP +nsWebBrowserContentPolicy::ShouldProcess(uint32_t aContentType, + nsIURI* aContentLocation, + nsIURI* aRequestingLocation, + nsISupports* aRequestingContext, + const nsACString& aMimeGuess, + nsISupports* aExtra, + nsIPrincipal* aRequestPrincipal, + int16_t* aShouldProcess) +{ + NS_PRECONDITION(aShouldProcess, "Null out param"); + + MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), + "We should only see external content policy types here."); + + *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 (aContentType != nsIContentPolicy::TYPE_OBJECT) { + return NS_OK; + } + + nsIDocShell* shell = NS_CP_GetDocShellFromContext(aRequestingContext); + if (shell && (!shell->PluginsAllowedInCurrentDoc())) { + *aShouldProcess = nsIContentPolicy::REJECT_TYPE; + } + + return NS_OK; +} diff --git a/embedding/browser/nsWebBrowserContentPolicy.h b/embedding/browser/nsWebBrowserContentPolicy.h new file mode 100644 index 000000000..e360e2110 --- /dev/null +++ b/embedding/browser/nsWebBrowserContentPolicy.h @@ -0,0 +1,26 @@ +/* -*- 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 +}; |