import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,15 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'nsIAppStartupNotifier.h',
]
SOURCES += [
'nsAppStartupNotifier.cpp',
]
FINAL_LIBRARY = 'xul'

View file

@ -0,0 +1,90 @@
/* -*- 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 "nsCOMPtr.h"
#include "nsString.h"
#include "nsXPIDLString.h"
#include "nsIServiceManager.h"
#include "nsICategoryManager.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsAppStartupNotifier.h"
#include "nsISimpleEnumerator.h"
NS_IMPL_ISUPPORTS(nsAppStartupNotifier, nsIObserver)
nsAppStartupNotifier::nsAppStartupNotifier()
{
}
nsAppStartupNotifier::~nsAppStartupNotifier()
{
}
NS_IMETHODIMP nsAppStartupNotifier::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
{
NS_ENSURE_ARG(aTopic);
nsresult rv;
// now initialize all startup listeners
nsCOMPtr<nsICategoryManager> categoryManager =
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISimpleEnumerator> enumerator;
rv = categoryManager->EnumerateCategory(aTopic,
getter_AddRefs(enumerator));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupports> entry;
while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
nsCOMPtr<nsISupportsCString> category = do_QueryInterface(entry, &rv);
if (NS_SUCCEEDED(rv)) {
nsAutoCString categoryEntry;
rv = category->GetData(categoryEntry);
nsXPIDLCString contractId;
categoryManager->GetCategoryEntry(aTopic,
categoryEntry.get(),
getter_Copies(contractId));
if (NS_SUCCEEDED(rv)) {
// If we see the word "service," in the beginning
// of the contractId then we create it as a service
// if not we do a createInstance
nsCOMPtr<nsISupports> startupInstance;
if (Substring(contractId, 0, 8).EqualsLiteral("service,"))
startupInstance = do_GetService(contractId.get() + 8, &rv);
else
startupInstance = do_CreateInstance(contractId, &rv);
if (NS_SUCCEEDED(rv)) {
// Try to QI to nsIObserver
nsCOMPtr<nsIObserver> startupObserver =
do_QueryInterface(startupInstance, &rv);
if (NS_SUCCEEDED(rv)) {
rv = startupObserver->Observe(nullptr, aTopic, nullptr);
// mainly for debugging if you want to know if your observer worked.
NS_ASSERTION(NS_SUCCEEDED(rv), "Startup Observer failed!\n");
}
}
else {
#ifdef DEBUG
nsAutoCString warnStr("Cannot create startup observer : ");
warnStr += contractId.get();
NS_WARNING(warnStr.get());
#endif
}
}
}
}
return NS_OK;
}

View file

@ -0,0 +1,30 @@
/* -*- Mode: C++; 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/. */
#ifndef nsAppStartupNotifier_h___
#define nsAppStartupNotifier_h___
#include "nsIAppStartupNotifier.h"
// {1F59B001-02C9-11d5-AE76-CC92F7DB9E03}
#define NS_APPSTARTUPNOTIFIER_CID \
{ 0x1f59b001, 0x2c9, 0x11d5, { 0xae, 0x76, 0xcc, 0x92, 0xf7, 0xdb, 0x9e, 0x3 } }
class nsAppStartupNotifier : public nsIObserver
{
public:
NS_DEFINE_STATIC_CID_ACCESSOR( NS_APPSTARTUPNOTIFIER_CID )
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
nsAppStartupNotifier();
protected:
virtual ~nsAppStartupNotifier();
};
#endif /* nsAppStartupNotifier_h___ */

View file

@ -0,0 +1,59 @@
/* -*- 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/. */
#ifndef nsIAppStartupNotifier_h___
#define nsIAppStartupNotifier_h___
#include "nsIObserver.h"
/*
Some components need to be run at the startup of mozilla or embedding - to
start new services etc.
This interface provides a generic way to start up arbitrary components
without requiring them to hack into main1() (or into NS_InitEmbedding) as
it's currently being done for services such as wallet, command line handlers
etc.
We will have a category called "app-startup" which components register
themselves in using the CategoryManager.
Components can also (optionally) add the word "service," as a prefix
to the "value" they pass in during a call to AddCategoryEntry() as
shown below:
categoryManager->AddCategoryEntry(APPSTARTUP_CATEGORY, "testcomp",
"service," NS_WALLETSERVICE_CONTRACTID
true, true,
getter_Copies(previous));
Presence of the "service" keyword indicates the components desire to
be started as a service. When the "service" keyword is not present
we just do a do_CreateInstance.
When mozilla starts (and when NS_InitEmbedding()) is invoked
we create an instance of the AppStartupNotifier component (which
implements nsIObserver) and invoke its Observe() method.
Observe() will enumerate the components registered into the
APPSTARTUP_CATEGORY and notify them that startup has begun
and release them.
*/
#define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1"
#define APPSTARTUP_CATEGORY "app-startup"
#define APPSTARTUP_TOPIC "app-startup"
/*
Please note that there's not a new interface in this file.
We're just leveraging nsIObserver instead of creating a
new one
This file exists solely to provide the defines above
*/
#endif /* nsIAppStartupNotifier_h___ */

View file

@ -0,0 +1,38 @@
# -*- 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 += [
'nsEmbeddingModule.cpp',
]
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../appstartup',
'../commandhandler',
'../find',
'../printingui/ipc',
'../webbrowserpersist',
'../windowwatcher',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
DEFINES['PROXY_PRINTING'] = 1
LOCAL_INCLUDES += [
'../printingui/win',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
DEFINES['PROXY_PRINTING'] = 1
LOCAL_INCLUDES += [
'../printingui/mac',
]
if CONFIG['MOZ_PDF_PRINTING']:
DEFINES['PROXY_PRINTING'] = 1
LOCAL_INCLUDES += [
'../printingui/unixshared',
]
include('/ipc/chromium/chromium-config.mozbuild')

View file

@ -0,0 +1,120 @@
/* -*- 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 "mozilla/ModuleUtils.h"
#include "nsDialogParamBlock.h"
#include "nsWindowWatcher.h"
#include "nsAppStartupNotifier.h"
#include "nsFind.h"
#include "nsWebBrowserFind.h"
#include "nsWebBrowserPersist.h"
#include "nsCommandManager.h"
#include "nsControllerCommandTable.h"
#include "nsCommandParams.h"
#include "nsCommandGroup.h"
#include "nsBaseCommandController.h"
#include "nsNetCID.h"
#include "nsEmbedCID.h"
#ifdef NS_PRINTING
#include "nsPrintingPromptService.h"
#include "nsPrintingProxy.h"
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWindowWatcher, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppStartupNotifier)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFind)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebBrowserFind)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebBrowserPersist)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsControllerCommandTable)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCommandManager)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCommandParams)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsControllerCommandGroup)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBaseCommandController)
#ifdef MOZ_XUL
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDialogParamBlock)
#ifdef NS_PRINTING
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintingPromptService, Init)
#ifdef PROXY_PRINTING
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsPrintingProxy,
nsPrintingProxy::GetInstance)
#endif
#endif
#endif
#ifdef MOZ_XUL
NS_DEFINE_NAMED_CID(NS_DIALOGPARAMBLOCK_CID);
#ifdef NS_PRINTING
NS_DEFINE_NAMED_CID(NS_PRINTINGPROMPTSERVICE_CID);
#endif
#endif
NS_DEFINE_NAMED_CID(NS_WINDOWWATCHER_CID);
NS_DEFINE_NAMED_CID(NS_FIND_CID);
NS_DEFINE_NAMED_CID(NS_WEB_BROWSER_FIND_CID);
NS_DEFINE_NAMED_CID(NS_APPSTARTUPNOTIFIER_CID);
NS_DEFINE_NAMED_CID(NS_WEBBROWSERPERSIST_CID);
NS_DEFINE_NAMED_CID(NS_CONTROLLERCOMMANDTABLE_CID);
NS_DEFINE_NAMED_CID(NS_COMMAND_MANAGER_CID);
NS_DEFINE_NAMED_CID(NS_COMMAND_PARAMS_CID);
NS_DEFINE_NAMED_CID(NS_CONTROLLER_COMMAND_GROUP_CID);
NS_DEFINE_NAMED_CID(NS_BASECOMMANDCONTROLLER_CID);
static const mozilla::Module::CIDEntry kEmbeddingCIDs[] = {
#ifdef MOZ_XUL
{ &kNS_DIALOGPARAMBLOCK_CID, false, nullptr, nsDialogParamBlockConstructor },
#ifdef NS_PRINTING
#ifdef PROXY_PRINTING
{ &kNS_PRINTINGPROMPTSERVICE_CID, false, nullptr, nsPrintingPromptServiceConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTINGPROMPTSERVICE_CID, false, nullptr, nsPrintingProxyConstructor,
mozilla::Module::CONTENT_PROCESS_ONLY },
#else
{ &kNS_PRINTINGPROMPTSERVICE_CID, false, nullptr, nsPrintingPromptServiceConstructor },
#endif
#endif
#endif
{ &kNS_WINDOWWATCHER_CID, false, nullptr, nsWindowWatcherConstructor },
{ &kNS_FIND_CID, false, nullptr, nsFindConstructor },
{ &kNS_WEB_BROWSER_FIND_CID, false, nullptr, nsWebBrowserFindConstructor },
{ &kNS_APPSTARTUPNOTIFIER_CID, false, nullptr, nsAppStartupNotifierConstructor },
{ &kNS_WEBBROWSERPERSIST_CID, false, nullptr, nsWebBrowserPersistConstructor },
{ &kNS_CONTROLLERCOMMANDTABLE_CID, false, nullptr, nsControllerCommandTableConstructor },
{ &kNS_COMMAND_MANAGER_CID, false, nullptr, nsCommandManagerConstructor },
{ &kNS_COMMAND_PARAMS_CID, false, nullptr, nsCommandParamsConstructor },
{ &kNS_CONTROLLER_COMMAND_GROUP_CID, false, nullptr, nsControllerCommandGroupConstructor },
{ &kNS_BASECOMMANDCONTROLLER_CID, false, nullptr, nsBaseCommandControllerConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kEmbeddingContracts[] = {
#ifdef MOZ_XUL
{ NS_DIALOGPARAMBLOCK_CONTRACTID, &kNS_DIALOGPARAMBLOCK_CID },
#ifdef NS_PRINTING
{ NS_PRINTINGPROMPTSERVICE_CONTRACTID, &kNS_PRINTINGPROMPTSERVICE_CID },
#endif
#endif
{ NS_WINDOWWATCHER_CONTRACTID, &kNS_WINDOWWATCHER_CID },
{ NS_FIND_CONTRACTID, &kNS_FIND_CID },
{ NS_WEB_BROWSER_FIND_CONTRACTID, &kNS_WEB_BROWSER_FIND_CID },
{ NS_APPSTARTUPNOTIFIER_CONTRACTID, &kNS_APPSTARTUPNOTIFIER_CID },
{ NS_WEBBROWSERPERSIST_CONTRACTID, &kNS_WEBBROWSERPERSIST_CID },
{ NS_CONTROLLERCOMMANDTABLE_CONTRACTID, &kNS_CONTROLLERCOMMANDTABLE_CID },
{ NS_COMMAND_MANAGER_CONTRACTID, &kNS_COMMAND_MANAGER_CID },
{ NS_COMMAND_PARAMS_CONTRACTID, &kNS_COMMAND_PARAMS_CID },
{ NS_CONTROLLER_COMMAND_GROUP_CONTRACTID, &kNS_CONTROLLER_COMMAND_GROUP_CID },
{ NS_BASECOMMANDCONTROLLER_CONTRACTID, &kNS_BASECOMMANDCONTROLLER_CID },
{ nullptr }
};
static const mozilla::Module kEmbeddingModule = {
mozilla::Module::kVersion,
kEmbeddingCIDs,
kEmbeddingContracts
};
NSMODULE_DEFN(embedcomponents) = &kEmbeddingModule;

View file

@ -0,0 +1,26 @@
# -*- 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/.
XPIDL_SOURCES += [
'nsICommandManager.idl',
'nsICommandParams.idl',
'nsIControllerCommand.idl',
'nsIControllerCommandTable.idl',
'nsIControllerContext.idl',
'nsPICommandUpdater.idl',
]
XPIDL_MODULE = 'commandhandler'
UNIFIED_SOURCES += [
'nsBaseCommandController.cpp',
'nsCommandGroup.cpp',
'nsCommandManager.cpp',
'nsCommandParams.cpp',
'nsControllerCommandTable.cpp',
]
FINAL_LIBRARY = 'xul'

View file

@ -0,0 +1,184 @@
/* -*- 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 "nsString.h"
#include "nsIComponentManager.h"
#include "nsBaseCommandController.h"
#include "nsString.h"
#include "nsWeakPtr.h"
NS_IMPL_ADDREF(nsBaseCommandController)
NS_IMPL_RELEASE(nsBaseCommandController)
NS_INTERFACE_MAP_BEGIN(nsBaseCommandController)
NS_INTERFACE_MAP_ENTRY(nsIController)
NS_INTERFACE_MAP_ENTRY(nsICommandController)
NS_INTERFACE_MAP_ENTRY(nsIControllerContext)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIControllerContext)
NS_INTERFACE_MAP_END
nsBaseCommandController::nsBaseCommandController()
: mCommandContextRawPtr(nullptr)
{
}
nsBaseCommandController::~nsBaseCommandController()
{
}
NS_IMETHODIMP
nsBaseCommandController::Init(nsIControllerCommandTable* aCommandTable)
{
nsresult rv = NS_OK;
if (aCommandTable) {
mCommandTable = aCommandTable;
} else {
mCommandTable =
do_CreateInstance(NS_CONTROLLERCOMMANDTABLE_CONTRACTID, &rv);
}
return rv;
}
NS_IMETHODIMP
nsBaseCommandController::SetCommandContext(nsISupports* aCommandContext)
{
mCommandContextWeakPtr = nullptr;
mCommandContextRawPtr = nullptr;
if (aCommandContext) {
nsCOMPtr<nsISupportsWeakReference> weak = do_QueryInterface(aCommandContext);
if (weak) {
nsresult rv =
weak->GetWeakReference(getter_AddRefs(mCommandContextWeakPtr));
NS_ENSURE_SUCCESS(rv, rv);
} else {
mCommandContextRawPtr = aCommandContext;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsBaseCommandController::GetInterface(const nsIID& aIID, void** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
if (NS_SUCCEEDED(QueryInterface(aIID, aResult))) {
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIControllerCommandTable))) {
if (mCommandTable) {
return mCommandTable->QueryInterface(aIID, aResult);
}
return NS_ERROR_NOT_INITIALIZED;
}
return NS_NOINTERFACE;
}
/* =======================================================================
* nsIController
* ======================================================================= */
NS_IMETHODIMP
nsBaseCommandController::IsCommandEnabled(const char* aCommand, bool* aResult)
{
NS_ENSURE_ARG_POINTER(aCommand);
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_STATE(mCommandTable);
nsISupports* context = mCommandContextRawPtr;
nsCOMPtr<nsISupports> weak;
if (!context) {
weak = do_QueryReferent(mCommandContextWeakPtr);
context = weak;
}
return mCommandTable->IsCommandEnabled(aCommand, context, aResult);
}
NS_IMETHODIMP
nsBaseCommandController::SupportsCommand(const char* aCommand, bool* aResult)
{
NS_ENSURE_ARG_POINTER(aCommand);
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_STATE(mCommandTable);
nsISupports* context = mCommandContextRawPtr;
nsCOMPtr<nsISupports> weak;
if (!context) {
weak = do_QueryReferent(mCommandContextWeakPtr);
context = weak;
}
return mCommandTable->SupportsCommand(aCommand, context, aResult);
}
NS_IMETHODIMP
nsBaseCommandController::DoCommand(const char* aCommand)
{
NS_ENSURE_ARG_POINTER(aCommand);
NS_ENSURE_STATE(mCommandTable);
nsISupports* context = mCommandContextRawPtr;
nsCOMPtr<nsISupports> weak;
if (!context) {
weak = do_QueryReferent(mCommandContextWeakPtr);
context = weak;
}
return mCommandTable->DoCommand(aCommand, context);
}
NS_IMETHODIMP
nsBaseCommandController::DoCommandWithParams(const char* aCommand,
nsICommandParams* aParams)
{
NS_ENSURE_ARG_POINTER(aCommand);
NS_ENSURE_STATE(mCommandTable);
nsISupports* context = mCommandContextRawPtr;
nsCOMPtr<nsISupports> weak;
if (!context) {
weak = do_QueryReferent(mCommandContextWeakPtr);
context = weak;
}
return mCommandTable->DoCommandParams(aCommand, aParams, context);
}
NS_IMETHODIMP
nsBaseCommandController::GetCommandStateWithParams(const char* aCommand,
nsICommandParams* aParams)
{
NS_ENSURE_ARG_POINTER(aCommand);
NS_ENSURE_STATE(mCommandTable);
nsISupports* context = mCommandContextRawPtr;
nsCOMPtr<nsISupports> weak;
if (!context) {
weak = do_QueryReferent(mCommandContextWeakPtr);
context = weak;
}
return mCommandTable->GetCommandState(aCommand, aParams, context);
}
NS_IMETHODIMP
nsBaseCommandController::OnEvent(const char* aEventName)
{
NS_ENSURE_ARG_POINTER(aEventName);
return NS_OK;
}
NS_IMETHODIMP
nsBaseCommandController::GetSupportedCommands(uint32_t* aCount,
char*** aCommands)
{
NS_ENSURE_STATE(mCommandTable);
return mCommandTable->GetSupportedCommands(aCount, aCommands);
}

View file

@ -0,0 +1,49 @@
/* -*- 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 nsBaseCommandController_h__
#define nsBaseCommandController_h__
#define NS_BASECOMMANDCONTROLLER_CID \
{ 0xbf88b48c, 0xfd8e, 0x40b4, { 0xba, 0x36, 0xc7, 0xc3, 0xad, 0x6d, 0x8a, 0xc9 } }
#define NS_BASECOMMANDCONTROLLER_CONTRACTID \
"@mozilla.org/embedcomp/base-command-controller;1"
#include "nsIController.h"
#include "nsIControllerContext.h"
#include "nsIControllerCommandTable.h"
#include "nsIInterfaceRequestor.h"
#include "nsIWeakReferenceUtils.h"
// The base editor controller is used for both text widgets, and all other text
// and html editing
class nsBaseCommandController
: public nsIController
, public nsIControllerContext
, public nsIInterfaceRequestor
, public nsICommandController
{
public:
nsBaseCommandController();
NS_DECL_ISUPPORTS
NS_DECL_NSICONTROLLER
NS_DECL_NSICOMMANDCONTROLLER
NS_DECL_NSICONTROLLERCONTEXT
NS_DECL_NSIINTERFACEREQUESTOR
protected:
virtual ~nsBaseCommandController();
private:
nsWeakPtr mCommandContextWeakPtr;
nsISupports* mCommandContextRawPtr;
// Our reference to the command manager
nsCOMPtr<nsIControllerCommandTable> mCommandTable;
};
#endif /* nsBaseCommandController_h_ */

View file

@ -0,0 +1,296 @@
/* -*- 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 "nsString.h"
#include "nsReadableUtils.h"
#include "nsTArray.h"
#include "nsISimpleEnumerator.h"
#include "nsXPCOM.h"
#include "nsSupportsPrimitives.h"
#include "nsIComponentManager.h"
#include "nsCommandGroup.h"
#include "nsIControllerCommand.h"
#include "nsCRT.h"
class nsGroupsEnumerator : public nsISimpleEnumerator
{
public:
explicit nsGroupsEnumerator(
nsControllerCommandGroup::GroupsHashtable& aInHashTable);
NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
protected:
virtual ~nsGroupsEnumerator();
nsresult Initialize();
protected:
nsControllerCommandGroup::GroupsHashtable& mHashTable;
int32_t mIndex;
const char** mGroupNames; // array of pointers to char16_t* in the hash table
bool mInitted;
};
/* Implementation file */
NS_IMPL_ISUPPORTS(nsGroupsEnumerator, nsISimpleEnumerator)
nsGroupsEnumerator::nsGroupsEnumerator(
nsControllerCommandGroup::GroupsHashtable& aInHashTable)
: mHashTable(aInHashTable)
, mIndex(-1)
, mGroupNames(nullptr)
, mInitted(false)
{
}
nsGroupsEnumerator::~nsGroupsEnumerator()
{
delete[] mGroupNames;
}
NS_IMETHODIMP
nsGroupsEnumerator::HasMoreElements(bool* aResult)
{
nsresult rv = NS_OK;
NS_ENSURE_ARG_POINTER(aResult);
if (!mInitted) {
rv = Initialize();
if (NS_FAILED(rv)) {
return rv;
}
}
*aResult = (mIndex < static_cast<int32_t>(mHashTable.Count()) - 1);
return NS_OK;
}
NS_IMETHODIMP
nsGroupsEnumerator::GetNext(nsISupports** aResult)
{
nsresult rv = NS_OK;
NS_ENSURE_ARG_POINTER(aResult);
if (!mInitted) {
rv = Initialize();
if (NS_FAILED(rv)) {
return rv;
}
}
mIndex++;
if (mIndex >= static_cast<int32_t>(mHashTable.Count())) {
return NS_ERROR_FAILURE;
}
const char* thisGroupName = mGroupNames[mIndex];
nsCOMPtr<nsISupportsCString> supportsString =
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
return rv;
}
supportsString->SetData(nsDependentCString(thisGroupName));
return CallQueryInterface(supportsString, aResult);
}
nsresult
nsGroupsEnumerator::Initialize()
{
if (mInitted) {
return NS_OK;
}
mGroupNames = new const char*[mHashTable.Count()];
if (!mGroupNames) {
return NS_ERROR_OUT_OF_MEMORY;
}
mIndex = 0;
for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
mGroupNames[mIndex] = iter.Key().Data();
mIndex++;
}
mIndex = -1;
mInitted = true;
return NS_OK;
}
class nsNamedGroupEnumerator : public nsISimpleEnumerator
{
public:
explicit nsNamedGroupEnumerator(nsTArray<nsCString>* aInArray);
NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
protected:
virtual ~nsNamedGroupEnumerator();
nsTArray<nsCString>* mGroupArray;
int32_t mIndex;
};
nsNamedGroupEnumerator::nsNamedGroupEnumerator(nsTArray<nsCString>* aInArray)
: mGroupArray(aInArray)
, mIndex(-1)
{
}
nsNamedGroupEnumerator::~nsNamedGroupEnumerator()
{
}
NS_IMPL_ISUPPORTS(nsNamedGroupEnumerator, nsISimpleEnumerator)
NS_IMETHODIMP
nsNamedGroupEnumerator::HasMoreElements(bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
int32_t arrayLen = mGroupArray ? mGroupArray->Length() : 0;
*aResult = (mIndex < arrayLen - 1);
return NS_OK;
}
NS_IMETHODIMP
nsNamedGroupEnumerator::GetNext(nsISupports** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
if (!mGroupArray) {
return NS_ERROR_FAILURE;
}
mIndex++;
if (mIndex >= int32_t(mGroupArray->Length())) {
return NS_ERROR_FAILURE;
}
const nsCString& thisGroupName = mGroupArray->ElementAt(mIndex);
nsresult rv;
nsCOMPtr<nsISupportsCString> supportsString =
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
return rv;
}
supportsString->SetData(thisGroupName);
return CallQueryInterface(supportsString, aResult);
}
NS_IMPL_ISUPPORTS(nsControllerCommandGroup, nsIControllerCommandGroup)
nsControllerCommandGroup::nsControllerCommandGroup()
{
}
nsControllerCommandGroup::~nsControllerCommandGroup()
{
ClearGroupsHash();
}
void
nsControllerCommandGroup::ClearGroupsHash()
{
mGroupsHash.Clear();
}
NS_IMETHODIMP
nsControllerCommandGroup::AddCommandToGroup(const char* aCommand,
const char* aGroup)
{
nsDependentCString groupKey(aGroup);
nsTArray<nsCString>* commandList = mGroupsHash.Get(groupKey);
if (!commandList) {
// make this list
commandList = new AutoTArray<nsCString, 8>;
mGroupsHash.Put(groupKey, commandList);
}
#ifdef DEBUG
nsCString* appended =
#endif
commandList->AppendElement(aCommand);
NS_ASSERTION(appended, "Append failed");
return NS_OK;
}
NS_IMETHODIMP
nsControllerCommandGroup::RemoveCommandFromGroup(const char* aCommand,
const char* aGroup)
{
nsDependentCString groupKey(aGroup);
nsTArray<nsCString>* commandList = mGroupsHash.Get(groupKey);
if (!commandList) {
return NS_OK; // no group
}
uint32_t numEntries = commandList->Length();
for (uint32_t i = 0; i < numEntries; i++) {
nsCString commandString = commandList->ElementAt(i);
if (nsDependentCString(aCommand) != commandString) {
commandList->RemoveElementAt(i);
break;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsControllerCommandGroup::IsCommandInGroup(const char* aCommand,
const char* aGroup, bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false;
nsDependentCString groupKey(aGroup);
nsTArray<nsCString>* commandList = mGroupsHash.Get(groupKey);
if (!commandList) {
return NS_OK; // no group
}
uint32_t numEntries = commandList->Length();
for (uint32_t i = 0; i < numEntries; i++) {
nsCString commandString = commandList->ElementAt(i);
if (nsDependentCString(aCommand) != commandString) {
*aResult = true;
break;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsControllerCommandGroup::GetGroupsEnumerator(nsISimpleEnumerator** aResult)
{
RefPtr<nsGroupsEnumerator> groupsEnum = new nsGroupsEnumerator(mGroupsHash);
groupsEnum.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsControllerCommandGroup::GetEnumeratorForGroup(const char* aGroup,
nsISimpleEnumerator** aResult)
{
nsDependentCString groupKey(aGroup);
nsTArray<nsCString>* commandList = mGroupsHash.Get(groupKey); // may be null
RefPtr<nsNamedGroupEnumerator> theGroupEnum =
new nsNamedGroupEnumerator(commandList);
theGroupEnum.forget(aResult);
return NS_OK;
}

View file

@ -0,0 +1,44 @@
/* -*- 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 nsCommandGroup_h__
#define nsCommandGroup_h__
#include "nsIController.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
// {ecd55a01-2780-11d5-a73c-ca641a6813bc}
#define NS_CONTROLLER_COMMAND_GROUP_CID \
{ 0xecd55a01, 0x2780, 0x11d5, { 0xa7, 0x3c, 0xca, 0x64, 0x1a, 0x68, 0x13, 0xbc } }
#define NS_CONTROLLER_COMMAND_GROUP_CONTRACTID \
"@mozilla.org/embedcomp/controller-command-group;1"
class nsControllerCommandGroup : public nsIControllerCommandGroup
{
public:
nsControllerCommandGroup();
NS_DECL_ISUPPORTS
NS_DECL_NSICONTROLLERCOMMANDGROUP
public:
typedef nsClassHashtable<nsCStringHashKey, nsTArray<nsCString>>
GroupsHashtable;
protected:
virtual ~nsControllerCommandGroup();
void ClearGroupsHash();
protected:
// Hash keyed on command group. This could be made more space-efficient,
// maybe with atoms.
GroupsHashtable mGroupsHash;
};
#endif // nsCommandGroup_h__

View file

@ -0,0 +1,262 @@
/* -*- 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 "nsString.h"
#include "nsIController.h"
#include "nsIControllers.h"
#include "nsIObserver.h"
#include "nsIComponentManager.h"
#include "nsServiceManagerUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsContentUtils.h"
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "nsPIWindowRoot.h"
#include "nsIFocusManager.h"
#include "nsCOMArray.h"
#include "nsCommandManager.h"
nsCommandManager::nsCommandManager()
: mWindow(nullptr)
{
}
nsCommandManager::~nsCommandManager()
{
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsCommandManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCommandManager)
tmp->mObserversTable.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCommandManager)
for (auto iter = tmp->mObserversTable.Iter(); !iter.Done(); iter.Next()) {
nsCommandManager::ObserverList* observers = iter.UserData();
int32_t numItems = observers->Length();
for (int32_t i = 0; i < numItems; ++i) {
cb.NoteXPCOMChild(observers->ElementAt(i));
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCommandManager)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCommandManager)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCommandManager)
NS_INTERFACE_MAP_ENTRY(nsICommandManager)
NS_INTERFACE_MAP_ENTRY(nsPICommandUpdater)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICommandManager)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsCommandManager::Init(mozIDOMWindowProxy* aWindow)
{
NS_ENSURE_ARG_POINTER(aWindow);
mWindow = aWindow; // weak ptr
return NS_OK;
}
NS_IMETHODIMP
nsCommandManager::CommandStatusChanged(const char* aCommandName)
{
ObserverList* commandObservers;
mObserversTable.Get(aCommandName, &commandObservers);
if (commandObservers) {
// XXX Should we worry about observers removing themselves from Observe()?
int32_t i, numItems = commandObservers->Length();
for (i = 0; i < numItems; ++i) {
nsCOMPtr<nsIObserver> observer = commandObservers->ElementAt(i);
// should we get the command state to pass here? This might be expensive.
observer->Observe(NS_ISUPPORTS_CAST(nsICommandManager*, this),
aCommandName,
u"command_status_changed");
}
}
return NS_OK;
}
#if 0
#pragma mark -
#endif
NS_IMETHODIMP
nsCommandManager::AddCommandObserver(nsIObserver* aCommandObserver,
const char* aCommandToObserve)
{
NS_ENSURE_ARG(aCommandObserver);
// XXX todo: handle special cases of aCommandToObserve being null, or empty
// for each command in the table, we make a list of observers for that command
ObserverList* commandObservers;
if (!mObserversTable.Get(aCommandToObserve, &commandObservers)) {
commandObservers = new ObserverList;
mObserversTable.Put(aCommandToObserve, commandObservers);
}
// need to check that this command observer hasn't already been registered
int32_t existingIndex = commandObservers->IndexOf(aCommandObserver);
if (existingIndex == -1) {
commandObservers->AppendElement(aCommandObserver);
} else {
NS_WARNING("Registering command observer twice on the same command");
}
return NS_OK;
}
NS_IMETHODIMP
nsCommandManager::RemoveCommandObserver(nsIObserver* aCommandObserver,
const char* aCommandObserved)
{
NS_ENSURE_ARG(aCommandObserver);
// XXX todo: handle special cases of aCommandToObserve being null, or empty
ObserverList* commandObservers;
if (!mObserversTable.Get(aCommandObserved, &commandObservers)) {
return NS_ERROR_UNEXPECTED;
}
commandObservers->RemoveElement(aCommandObserver);
return NS_OK;
}
NS_IMETHODIMP
nsCommandManager::IsCommandSupported(const char* aCommandName,
mozIDOMWindowProxy* aTargetWindow,
bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
nsCOMPtr<nsIController> controller;
GetControllerForCommand(aCommandName, aTargetWindow,
getter_AddRefs(controller));
*aResult = (controller.get() != nullptr);
return NS_OK;
}
NS_IMETHODIMP
nsCommandManager::IsCommandEnabled(const char* aCommandName,
mozIDOMWindowProxy* aTargetWindow,
bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
bool commandEnabled = false;
nsCOMPtr<nsIController> controller;
GetControllerForCommand(aCommandName, aTargetWindow,
getter_AddRefs(controller));
if (controller) {
controller->IsCommandEnabled(aCommandName, &commandEnabled);
}
*aResult = commandEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsCommandManager::GetCommandState(const char* aCommandName,
mozIDOMWindowProxy* aTargetWindow,
nsICommandParams* aCommandParams)
{
nsCOMPtr<nsIController> controller;
nsAutoString tValue;
nsresult rv = GetControllerForCommand(aCommandName, aTargetWindow,
getter_AddRefs(controller));
if (!controller) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsICommandController> commandController =
do_QueryInterface(controller);
if (commandController) {
rv = commandController->GetCommandStateWithParams(aCommandName,
aCommandParams);
} else {
rv = NS_ERROR_NOT_IMPLEMENTED;
}
return rv;
}
NS_IMETHODIMP
nsCommandManager::DoCommand(const char* aCommandName,
nsICommandParams* aCommandParams,
mozIDOMWindowProxy* aTargetWindow)
{
nsCOMPtr<nsIController> controller;
nsresult rv = GetControllerForCommand(aCommandName, aTargetWindow,
getter_AddRefs(controller));
if (!controller) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsICommandController> commandController =
do_QueryInterface(controller);
if (commandController && aCommandParams) {
rv = commandController->DoCommandWithParams(aCommandName, aCommandParams);
} else {
rv = controller->DoCommand(aCommandName);
}
return rv;
}
nsresult
nsCommandManager::GetControllerForCommand(const char* aCommand,
mozIDOMWindowProxy* aTargetWindow,
nsIController** aResult)
{
nsresult rv = NS_ERROR_FAILURE;
*aResult = nullptr;
// check if we're in content or chrome
// if we're not chrome we must have a target window or we bail
if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
if (!aTargetWindow) {
return rv;
}
// if a target window is specified, it must be the window we expect
if (aTargetWindow != mWindow) {
return NS_ERROR_FAILURE;
}
}
if (auto* targetWindow = nsPIDOMWindowOuter::From(aTargetWindow)) {
// get the controller for this particular window
nsCOMPtr<nsIControllers> controllers;
rv = targetWindow->GetControllers(getter_AddRefs(controllers));
if (NS_FAILED(rv)) {
return rv;
}
if (!controllers) {
return NS_ERROR_FAILURE;
}
// dispatch the command
return controllers->GetControllerForCommand(aCommand, aResult);
}
auto* window = nsPIDOMWindowOuter::From(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
// no target window; send command to focus controller
return root->GetControllerForCommand(aCommand, aResult);
}

View file

@ -0,0 +1,50 @@
/* -*- 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 nsCommandManager_h__
#define nsCommandManager_h__
#include "nsString.h"
#include "nsClassHashtable.h"
#include "nsWeakReference.h"
#include "nsICommandManager.h"
#include "nsPICommandUpdater.h"
#include "nsCycleCollectionParticipant.h"
class nsIController;
template<class E> class nsCOMArray;
class nsCommandManager
: public nsICommandManager
, public nsPICommandUpdater
, public nsSupportsWeakReference
{
public:
typedef nsTArray<nsCOMPtr<nsIObserver> > ObserverList;
nsCommandManager();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCommandManager, nsICommandManager)
NS_DECL_NSICOMMANDMANAGER
NS_DECL_NSPICOMMANDUPDATER
protected:
virtual ~nsCommandManager();
nsresult GetControllerForCommand(const char* aCommand,
mozIDOMWindowProxy* aDirectedToThisWindow,
nsIController** aResult);
protected:
nsClassHashtable<nsCharPtrHashKey, ObserverList> mObserversTable;
mozIDOMWindowProxy* mWindow; // weak ptr. The window should always outlive us
};
#endif // nsCommandManager_h__

View file

@ -0,0 +1,264 @@
/* -*- 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 "xpcom-config.h"
#include <new>
#include "nscore.h"
#include "nsCRT.h"
#include "nsCommandParams.h"
#include "mozilla/HashFunctions.h"
using namespace mozilla;
const PLDHashTableOps nsCommandParams::sHashOps =
{
HashKey,
HashMatchEntry,
HashMoveEntry,
HashClearEntry
};
NS_IMPL_ISUPPORTS(nsCommandParams, nsICommandParams)
nsCommandParams::nsCommandParams()
: mValuesHash(&sHashOps, sizeof(HashEntry), 2)
{
}
nsCommandParams::~nsCommandParams()
{
}
NS_IMETHODIMP
nsCommandParams::GetValueType(const char* aName, int16_t* aRetVal)
{
NS_ENSURE_ARG_POINTER(aRetVal);
HashEntry* foundEntry = GetNamedEntry(aName);
if (foundEntry) {
*aRetVal = foundEntry->mEntryType;
return NS_OK;
}
*aRetVal = eNoType;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCommandParams::GetBooleanValue(const char* aName, bool* aRetVal)
{
NS_ENSURE_ARG_POINTER(aRetVal);
HashEntry* foundEntry = GetNamedEntry(aName);
if (foundEntry && foundEntry->mEntryType == eBooleanType) {
*aRetVal = foundEntry->mData.mBoolean;
return NS_OK;
}
*aRetVal = false;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCommandParams::GetLongValue(const char* aName, int32_t* aRetVal)
{
NS_ENSURE_ARG_POINTER(aRetVal);
HashEntry* foundEntry = GetNamedEntry(aName);
if (foundEntry && foundEntry->mEntryType == eLongType) {
*aRetVal = foundEntry->mData.mLong;
return NS_OK;
}
*aRetVal = false;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCommandParams::GetDoubleValue(const char* aName, double* aRetVal)
{
NS_ENSURE_ARG_POINTER(aRetVal);
HashEntry* foundEntry = GetNamedEntry(aName);
if (foundEntry && foundEntry->mEntryType == eDoubleType) {
*aRetVal = foundEntry->mData.mDouble;
return NS_OK;
}
*aRetVal = 0.0;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCommandParams::GetStringValue(const char* aName, nsAString& aRetVal)
{
HashEntry* foundEntry = GetNamedEntry(aName);
if (foundEntry && foundEntry->mEntryType == eWStringType) {
NS_ASSERTION(foundEntry->mData.mString, "Null string");
aRetVal.Assign(*foundEntry->mData.mString);
return NS_OK;
}
aRetVal.Truncate();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCommandParams::GetCStringValue(const char* aName, char** aRetVal)
{
NS_ENSURE_ARG_POINTER(aRetVal);
HashEntry* foundEntry = GetNamedEntry(aName);
if (foundEntry && foundEntry->mEntryType == eStringType) {
NS_ASSERTION(foundEntry->mData.mCString, "Null string");
*aRetVal = ToNewCString(*foundEntry->mData.mCString);
return NS_OK;
}
*aRetVal = nullptr;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCommandParams::GetISupportsValue(const char* aName, nsISupports** aRetVal)
{
NS_ENSURE_ARG_POINTER(aRetVal);
HashEntry* foundEntry = GetNamedEntry(aName);
if (foundEntry && foundEntry->mEntryType == eISupportsType) {
NS_IF_ADDREF(*aRetVal = foundEntry->mISupports.get());
return NS_OK;
}
*aRetVal = nullptr;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCommandParams::SetBooleanValue(const char* aName, bool aValue)
{
HashEntry* foundEntry = GetOrMakeEntry(aName, eBooleanType);
if (!foundEntry) {
return NS_ERROR_OUT_OF_MEMORY;
}
foundEntry->mData.mBoolean = aValue;
return NS_OK;
}
NS_IMETHODIMP
nsCommandParams::SetLongValue(const char* aName, int32_t aValue)
{
HashEntry* foundEntry = GetOrMakeEntry(aName, eLongType);
if (!foundEntry) {
return NS_ERROR_OUT_OF_MEMORY;
}
foundEntry->mData.mLong = aValue;
return NS_OK;
}
NS_IMETHODIMP
nsCommandParams::SetDoubleValue(const char* aName, double aValue)
{
HashEntry* foundEntry = GetOrMakeEntry(aName, eDoubleType);
if (!foundEntry) {
return NS_ERROR_OUT_OF_MEMORY;
}
foundEntry->mData.mDouble = aValue;
return NS_OK;
}
NS_IMETHODIMP
nsCommandParams::SetStringValue(const char* aName, const nsAString& aValue)
{
HashEntry* foundEntry = GetOrMakeEntry(aName, eWStringType);
if (!foundEntry) {
return NS_ERROR_OUT_OF_MEMORY;
}
foundEntry->mData.mString = new nsString(aValue);
return NS_OK;
}
NS_IMETHODIMP
nsCommandParams::SetCStringValue(const char* aName, const char* aValue)
{
HashEntry* foundEntry = GetOrMakeEntry(aName, eStringType);
if (!foundEntry) {
return NS_ERROR_OUT_OF_MEMORY;
}
foundEntry->mData.mCString = new nsCString(aValue);
return NS_OK;
}
NS_IMETHODIMP
nsCommandParams::SetISupportsValue(const char* aName, nsISupports* aValue)
{
HashEntry* foundEntry = GetOrMakeEntry(aName, eISupportsType);
if (!foundEntry) {
return NS_ERROR_OUT_OF_MEMORY;
}
foundEntry->mISupports = aValue; // addrefs
return NS_OK;
}
NS_IMETHODIMP
nsCommandParams::RemoveValue(const char* aName)
{
mValuesHash.Remove((void*)aName);
return NS_OK;
}
nsCommandParams::HashEntry*
nsCommandParams::GetNamedEntry(const char* aName)
{
return static_cast<HashEntry*>(mValuesHash.Search((void*)aName));
}
nsCommandParams::HashEntry*
nsCommandParams::GetOrMakeEntry(const char* aName, uint8_t aEntryType)
{
auto foundEntry = static_cast<HashEntry*>(mValuesHash.Search((void*)aName));
if (foundEntry) { // reuse existing entry
foundEntry->Reset(aEntryType);
return foundEntry;
}
foundEntry = static_cast<HashEntry*>(mValuesHash.Add((void*)aName, fallible));
if (!foundEntry) {
return nullptr;
}
// Use placement new. Our ctor does not clobber keyHash, which is important.
new (foundEntry) HashEntry(aEntryType, aName);
return foundEntry;
}
PLDHashNumber
nsCommandParams::HashKey(const void* aKey)
{
return HashString((const char*)aKey);
}
bool
nsCommandParams::HashMatchEntry(const PLDHashEntryHdr* aEntry, const void* aKey)
{
const char* keyString = (const char*)aKey;
const HashEntry* thisEntry = static_cast<const HashEntry*>(aEntry);
return thisEntry->mEntryName.Equals(keyString);
}
void
nsCommandParams::HashMoveEntry(PLDHashTable* aTable,
const PLDHashEntryHdr* aFrom,
PLDHashEntryHdr* aTo)
{
const HashEntry* fromEntry = static_cast<const HashEntry*>(aFrom);
HashEntry* toEntry = static_cast<HashEntry*>(aTo);
new (toEntry) HashEntry(*fromEntry);
fromEntry->~HashEntry();
}
void
nsCommandParams::HashClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
{
HashEntry* thisEntry = static_cast<HashEntry*>(aEntry);
thisEntry->~HashEntry();
}

View file

@ -0,0 +1,131 @@
/* -*- 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 nsCommandParams_h__
#define nsCommandParams_h__
#include "nsString.h"
#include "nsICommandParams.h"
#include "nsCOMPtr.h"
#include "PLDHashTable.h"
class nsCommandParams : public nsICommandParams
{
public:
nsCommandParams();
NS_DECL_ISUPPORTS
NS_DECL_NSICOMMANDPARAMS
protected:
virtual ~nsCommandParams();
struct HashEntry : public PLDHashEntryHdr
{
nsCString mEntryName;
uint8_t mEntryType;
union
{
bool mBoolean;
int32_t mLong;
double mDouble;
nsString* mString;
nsCString* mCString;
} mData;
nsCOMPtr<nsISupports> mISupports;
HashEntry(uint8_t aType, const char* aEntryName)
: mEntryName(aEntryName)
, mEntryType(aType)
{
Reset(mEntryType);
}
HashEntry(const HashEntry& aRHS)
: mEntryType(aRHS.mEntryType)
{
Reset(mEntryType);
switch (mEntryType) {
case eBooleanType:
mData.mBoolean = aRHS.mData.mBoolean;
break;
case eLongType:
mData.mLong = aRHS.mData.mLong;
break;
case eDoubleType:
mData.mDouble = aRHS.mData.mDouble;
break;
case eWStringType:
NS_ASSERTION(aRHS.mData.mString, "Source entry has no string");
mData.mString = new nsString(*aRHS.mData.mString);
break;
case eStringType:
NS_ASSERTION(aRHS.mData.mCString, "Source entry has no string");
mData.mCString = new nsCString(*aRHS.mData.mCString);
break;
case eISupportsType:
mISupports = aRHS.mISupports.get();
break;
default:
NS_ERROR("Unknown type");
}
}
~HashEntry() { Reset(eNoType); }
void Reset(uint8_t aNewType)
{
switch (mEntryType) {
case eNoType:
break;
case eBooleanType:
mData.mBoolean = false;
break;
case eLongType:
mData.mLong = 0;
break;
case eDoubleType:
mData.mDouble = 0.0;
break;
case eWStringType:
delete mData.mString;
mData.mString = nullptr;
break;
case eISupportsType:
mISupports = nullptr;
break;
case eStringType:
delete mData.mCString;
mData.mCString = nullptr;
break;
default:
NS_ERROR("Unknown type");
}
mEntryType = aNewType;
}
};
HashEntry* GetNamedEntry(const char* aName);
HashEntry* GetOrMakeEntry(const char* aName, uint8_t aEntryType);
protected:
static PLDHashNumber HashKey(const void* aKey);
static bool HashMatchEntry(const PLDHashEntryHdr* aEntry, const void* aKey);
static void HashMoveEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aFrom,
PLDHashEntryHdr* aTo);
static void HashClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry);
PLDHashTable mValuesHash;
static const PLDHashTableOps sHashOps;
};
#endif // nsCommandParams_h__

View file

@ -0,0 +1,209 @@
/* -*- 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 "nsString.h"
#include "nsIControllerCommand.h"
#include "nsControllerCommandTable.h"
nsresult NS_NewControllerCommandTable(nsIControllerCommandTable** aResult);
// this value is used to size the hash table. Just a sensible upper bound
#define NUM_COMMANDS_LENGTH 32
nsControllerCommandTable::nsControllerCommandTable()
: mCommandsTable(NUM_COMMANDS_LENGTH)
, mMutable(true)
{
}
nsControllerCommandTable::~nsControllerCommandTable()
{
}
NS_IMPL_ISUPPORTS(nsControllerCommandTable, nsIControllerCommandTable,
nsISupportsWeakReference)
NS_IMETHODIMP
nsControllerCommandTable::MakeImmutable(void)
{
mMutable = false;
return NS_OK;
}
NS_IMETHODIMP
nsControllerCommandTable::RegisterCommand(const char* aCommandName,
nsIControllerCommand* aCommand)
{
NS_ENSURE_TRUE(mMutable, NS_ERROR_FAILURE);
mCommandsTable.Put(nsDependentCString(aCommandName), aCommand);
return NS_OK;
}
NS_IMETHODIMP
nsControllerCommandTable::UnregisterCommand(const char* aCommandName,
nsIControllerCommand* aCommand)
{
NS_ENSURE_TRUE(mMutable, NS_ERROR_FAILURE);
nsDependentCString commandKey(aCommandName);
if (!mCommandsTable.Get(commandKey, nullptr)) {
return NS_ERROR_FAILURE;
}
mCommandsTable.Remove(commandKey);
return NS_OK;
}
NS_IMETHODIMP
nsControllerCommandTable::FindCommandHandler(const char* aCommandName,
nsIControllerCommand** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = nullptr;
nsCOMPtr<nsIControllerCommand> foundCommand;
mCommandsTable.Get(nsDependentCString(aCommandName),
getter_AddRefs(foundCommand));
if (!foundCommand) {
return NS_ERROR_FAILURE;
}
foundCommand.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsControllerCommandTable::IsCommandEnabled(const char* aCommandName,
nsISupports* aCommandRefCon,
bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false;
nsCOMPtr<nsIControllerCommand> commandHandler;
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
if (!commandHandler) {
NS_WARNING("Controller command table asked about a command that it does "
"not handle");
return NS_OK;
}
return commandHandler->IsCommandEnabled(aCommandName, aCommandRefCon,
aResult);
}
NS_IMETHODIMP
nsControllerCommandTable::UpdateCommandState(const char* aCommandName,
nsISupports* aCommandRefCon)
{
nsCOMPtr<nsIControllerCommand> commandHandler;
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
if (!commandHandler) {
NS_WARNING("Controller command table asked to update the state of a "
"command that it does not handle");
return NS_OK;
}
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsControllerCommandTable::SupportsCommand(const char* aCommandName,
nsISupports* aCommandRefCon,
bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
// XXX: need to check the readonly and disabled states
*aResult = false;
nsCOMPtr<nsIControllerCommand> commandHandler;
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
*aResult = (commandHandler.get() != nullptr);
return NS_OK;
}
NS_IMETHODIMP
nsControllerCommandTable::DoCommand(const char* aCommandName,
nsISupports* aCommandRefCon)
{
nsCOMPtr<nsIControllerCommand> commandHandler;
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
if (!commandHandler) {
NS_WARNING("Controller command table asked to do a command that it does "
"not handle");
return NS_OK;
}
return commandHandler->DoCommand(aCommandName, aCommandRefCon);
}
NS_IMETHODIMP
nsControllerCommandTable::DoCommandParams(const char* aCommandName,
nsICommandParams* aParams,
nsISupports* aCommandRefCon)
{
nsCOMPtr<nsIControllerCommand> commandHandler;
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
if (!commandHandler) {
NS_WARNING("Controller command table asked to do a command that it does "
"not handle");
return NS_OK;
}
return commandHandler->DoCommandParams(aCommandName, aParams, aCommandRefCon);
}
NS_IMETHODIMP
nsControllerCommandTable::GetCommandState(const char* aCommandName,
nsICommandParams* aParams,
nsISupports* aCommandRefCon)
{
nsCOMPtr<nsIControllerCommand> commandHandler;
FindCommandHandler(aCommandName, getter_AddRefs(commandHandler));
if (!commandHandler) {
NS_WARNING("Controller command table asked to do a command that it does "
"not handle");
return NS_OK;
}
return commandHandler->GetCommandStateParams(aCommandName, aParams,
aCommandRefCon);
}
NS_IMETHODIMP
nsControllerCommandTable::GetSupportedCommands(uint32_t* aCount,
char*** aCommands)
{
char** commands =
static_cast<char**>(moz_xmalloc(sizeof(char*) * mCommandsTable.Count()));
*aCount = mCommandsTable.Count();
*aCommands = commands;
for (auto iter = mCommandsTable.Iter(); !iter.Done(); iter.Next()) {
*commands = ToNewCString(iter.Key());
commands++;
}
return NS_OK;
}
nsresult
NS_NewControllerCommandTable(nsIControllerCommandTable** aResult)
{
NS_PRECONDITION(aResult != nullptr, "null ptr");
if (!aResult) {
return NS_ERROR_NULL_POINTER;
}
nsControllerCommandTable* newCommandTable = new nsControllerCommandTable();
NS_ADDREF(newCommandTable);
*aResult = newCommandTable;
return NS_OK;
}

View file

@ -0,0 +1,36 @@
/* -*- 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 nsControllerCommandTable_h_
#define nsControllerCommandTable_h_
#include "nsIControllerCommandTable.h"
#include "nsWeakReference.h"
#include "nsInterfaceHashtable.h"
class nsIControllerCommand;
class nsControllerCommandTable final
: public nsIControllerCommandTable
, public nsSupportsWeakReference
{
public:
nsControllerCommandTable();
NS_DECL_ISUPPORTS
NS_DECL_NSICONTROLLERCOMMANDTABLE
protected:
virtual ~nsControllerCommandTable();
// Hash table of nsIControllerCommands, keyed by command name.
nsInterfaceHashtable<nsCStringHashKey, nsIControllerCommand> mCommandsTable;
// Are we mutable?
bool mMutable;
};
#endif // nsControllerCommandTable_h_

View file

@ -0,0 +1,118 @@
/* -*- Mode: C++; 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"
#include "nsIObserver.idl"
#include "nsICommandParams.idl"
interface mozIDOMWindowProxy;
/*
* nsICommandManager is an interface used to executing user-level commands,
* and getting the state of available commands.
*
* Commands are identified by strings, which are documented elsewhere.
* In addition, the list of required and optional parameters for
* each command, that are passed in via the nsICommandParams, are
* also documented elsewhere. (Where? Need a good location for this).
*/
[scriptable, uuid(bb5a1730-d83b-4fa2-831b-35b9d5842e84)]
interface nsICommandManager : nsISupports
{
/*
* Register an observer on the specified command. The observer's Observe
* method will get called when the state (enabled/disbaled, or toggled etc)
* of the command changes.
*
* You can register the same observer on multiple commmands by calling this
* multiple times.
*/
void addCommandObserver(in nsIObserver aCommandObserver,
in string aCommandToObserve);
/*
* Stop an observer from observering the specified command. If the observer
* was also registered on ther commands, they will continue to be observed.
*
* Passing an empty string in 'aCommandObserved' will remove the observer
* from all commands.
*/
void removeCommandObserver(in nsIObserver aCommandObserver,
in string aCommandObserved);
/*
* Ask the command manager if the specified command is supported.
* If aTargetWindow is null, the focused window is used.
*
*/
boolean isCommandSupported(in string aCommandName,
in mozIDOMWindowProxy aTargetWindow);
/*
* Ask the command manager if the specified command is currently.
* enabled.
* If aTargetWindow is null, the focused window is used.
*/
boolean isCommandEnabled(in string aCommandName,
in mozIDOMWindowProxy aTargetWindow);
/*
* Get the state of the specified commands.
*
* On input: aCommandParams filled in with values that the caller cares
* about, most of which are command-specific (see the command documentation
* for details). One boolean value, "enabled", applies to all commands,
* and, in return will be set to indicate whether the command is enabled
* (equivalent to calling isCommandEnabled).
*
* aCommandName is the name of the command that needs the state
* aTargetWindow is the source of command controller
* (null means use focus controller)
* On output: aCommandParams: values set by the caller filled in with
* state from the command.
*/
void getCommandState(in string aCommandName,
in mozIDOMWindowProxy aTargetWindow,
/* inout */ in nsICommandParams aCommandParams);
/*
* Execute the specified command.
* The command will be executed in aTargetWindow if it is specified.
* If aTargetWindow is null, it will go to the focused window.
*
* param: aCommandParams, a list of name-value pairs of command parameters,
* may be null for parameter-less commands.
*
*/
void doCommand(in string aCommandName,
in nsICommandParams aCommandParams,
in mozIDOMWindowProxy aTargetWindow);
};
/*
Arguments to observers "Observe" method are as follows:
void Observe( in nsISupports aSubject, // The nsICommandManager calling this Observer
in string aTopic, // Name of the command
in wstring aDummy ); // unused
*/
// {64edb481-0c04-11d5-a73c-e964b968b0bc}
%{C++
#define NS_COMMAND_MANAGER_CID \
{ 0x64edb481, 0x0c04, 0x11d5, { 0xa7, 0x3c, 0xe9, 0x64, 0xb9, 0x68, 0xb0, 0xbc } }
#define NS_COMMAND_MANAGER_CONTRACTID \
"@mozilla.org/embedcomp/command-manager;1"
%}

View file

@ -0,0 +1,85 @@
/* -*- Mode: C++; 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"
/*
* nsICommandParams is used to pass parameters to commands executed
* via nsICommandManager, and to get command state.
*
*/
[scriptable, uuid(b1fdf3c4-74e3-4f7d-a14d-2b76bcf53482)]
interface nsICommandParams : nsISupports
{
/*
* List of primitive types for parameter values.
*/
const short eNoType = 0; /* Only used for sanity checking */
const short eBooleanType = 1;
const short eLongType = 2;
const short eDoubleType = 3;
const short eWStringType = 4;
const short eISupportsType = 5;
const short eStringType = 6;
/*
* getValueType
*
* Get the type of a specified parameter
*/
short getValueType(in string name);
/*
* get_Value
*
* Get the value of a specified parameter. Will return
* an error if the parameter does not exist, or if the value
* is of the wrong type (no coercion is performed for you).
*
* nsISupports values can contain any XPCOM interface,
* as documented for the command. It is permissible
* for it to contain nsICommandParams, but not *this*
* one (i.e. self-containing is not allowed).
*/
boolean getBooleanValue(in string name);
long getLongValue(in string name);
double getDoubleValue(in string name);
AString getStringValue(in string name);
string getCStringValue(in string name);
nsISupports getISupportsValue(in string name);
/*
* set_Value
*
* Set the value of a specified parameter (thus creating
* an entry for it).
*
* nsISupports values can contain any XPCOM interface,
* as documented for the command. It is permissible
* for it to contain nsICommandParams, but not *this*
* one (i.e. self-containing is not allowed).
*/
void setBooleanValue(in string name, in boolean value);
void setLongValue(in string name, in long value);
void setDoubleValue(in string name, in double value);
void setStringValue(in string name, in AString value);
void setCStringValue(in string name, in string value);
void setISupportsValue(in string name, in nsISupports value);
/*
* removeValue
*
* Remove the specified parameter from the list.
*/
void removeValue(in string name);
};
// {f7fa4581-238e-11d5-a73c-ab64fb68f2bc}
%{C++
#define NS_COMMAND_PARAMS_CID { 0xf7fa4581, 0x238e, 0x11d5, { 0xa7, 0x3c, 0xab, 0x64, 0xfb, 0x68, 0xf2, 0xbc } }
#define NS_COMMAND_PARAMS_CONTRACTID "@mozilla.org/embedcomp/command-params;1"
%}

View file

@ -0,0 +1,51 @@
/* -*- Mode: C++; 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"
#include "nsICommandParams.idl"
/**
* nsIControllerCommand
*
* A generic command interface. You can register an nsIControllerCommand
* with the nsIControllerCommandTable.
*/
[scriptable, uuid(0eae9a46-1dd2-11b2-aca0-9176f05fe9db)]
interface nsIControllerCommand : nsISupports
{
/**
* Returns true if the command is currently enabled. An nsIControllerCommand
* can implement more than one commands; say, a group of related commands
* (e.g. delete left/delete right). Because of this, the command name is
* passed to each method.
*
* @param aCommandName the name of the command for which we want the enabled
* state.
* @param aCommandContext a cookie held by the nsIControllerCommandTable,
* allowing the command to get some context information.
* The contents of this cookie are implementation-defined.
*/
boolean isCommandEnabled(in string aCommandName, in nsISupports aCommandContext);
void getCommandStateParams(in string aCommandName, in nsICommandParams aParams, in nsISupports aCommandContext);
/**
* Execute the name command.
*
* @param aCommandName the name of the command to execute.
*
* @param aCommandContext a cookie held by the nsIControllerCommandTable,
* allowing the command to get some context information.
* The contents of this cookie are implementation-defined.
*/
void doCommand(in string aCommandName, in nsISupports aCommandContext);
void doCommandParams(in string aCommandName, in nsICommandParams aParams, in nsISupports aCommandContext);
};

View file

@ -0,0 +1,100 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "nsIControllerCommand.idl"
#include "nsICommandParams.idl"
/**
* nsIControllerCommandTable
*
* An interface via which a controller can maintain a series of commands,
* and efficiently dispatch commands to their respective handlers.
*
* Controllers that use an nsIControllerCommandTable should support
* nsIInterfaceRequestor, and be able to return an interface to their
* controller command table via getInterface().
*
*/
[scriptable, uuid(c847f90e-b8f3-49db-a4df-8867831f2800)]
interface nsIControllerCommandTable : nsISupports
{
/**
* Make this command table immutable, so that commands cannot
* be registered or unregistered. Some command tables are made
* mutable after command registration so that they can be
* used as singletons.
*/
void makeImmutable();
/**
* Register and unregister commands with the command table.
*
* @param aCommandName the name of the command under which to register or
* unregister the given command handler.
*
* @param aCommand the handler for this command.
*/
void registerCommand(in string aCommandName, in nsIControllerCommand aCommand);
void unregisterCommand(in string aCommandName, in nsIControllerCommand aCommand);
/**
* Find the command handler which has been registered to handle the named command.
*
* @param aCommandName the name of the command to find the handler for.
*/
nsIControllerCommand findCommandHandler(in string aCommandName);
/**
* Get whether the named command is enabled.
*
* @param aCommandName the name of the command to test
* @param aCommandRefCon the command context data
*/
boolean isCommandEnabled(in string aCommandName, in nsISupports aCommandRefCon);
/**
* Tell the command to update its state (if it is a state updating command)
*
* @param aCommandName the name of the command to update
* @param aCommandRefCon the command context data
*/
void updateCommandState(in string aCommandName, in nsISupports aCommandRefCon);
/**
* Get whether the named command is supported.
*
* @param aCommandName the name of the command to test
* @param aCommandRefCon the command context data
*/
boolean supportsCommand(in string aCommandName, in nsISupports aCommandRefCon);
/**
* Execute the named command.
*
* @param aCommandName the name of the command to execute
* @param aCommandRefCon the command context data
*/
void doCommand(in string aCommandName, in nsISupports aCommandRefCon);
void doCommandParams(in string aCommandName, in nsICommandParams aParam, in nsISupports aCommandRefCon);
void getCommandState(in string aCommandName, in nsICommandParams aParam, in nsISupports aCommandRefCon);
void getSupportedCommands(out unsigned long count,
[array, size_is(count), retval] out string commands);
};
%{C++
// {670ee5da-6ad5-11d7-9950-000393636592}
#define NS_CONTROLLERCOMMANDTABLE_CID \
{0x670ee5da, 0x6ad5, 0x11d7, \
{ 0x99, 0x50, 0x00, 0x03, 0x93, 0x63, 0x65, 0x92 }}
#define NS_CONTROLLERCOMMANDTABLE_CONTRACTID \
"@mozilla.org/embedcomp/controller-command-table;1"
%}

View file

@ -0,0 +1,35 @@
/* -*- Mode: C++; 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"
#include "nsIControllerCommandTable.idl"
[scriptable, uuid(47B82B60-A36F-4167-8072-6F421151ED50)]
interface nsIControllerContext : nsISupports
{
/**
* Init the controller, optionally passing a controller
* command table.
*
* @param aCommandTable a command table, used internally
* by this controller. May be null, in
* which case the controller will create
* a new, empty table.
*/
void init(in nsIControllerCommandTable aCommandTable);
/**
* Set a context on this controller, which is passed
* to commands to give them some context when they execute.
*
* @param aCommandContext the context passed to commands.
* Note that this is *not* addreffed by the
* controller, and so needs to outlive it,
* or be nulled out.
*/
void setCommandContext(in nsISupports aCommandContext);
};

View file

@ -0,0 +1,39 @@
/* -*- Mode: C++; 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 mozIDOMWindowProxy;
/*
The nsPICommandUpdater interface is used by modules that implement
commands, to tell the command manager that commands need updating.
This is a private interface; embedders should not use it.
Command-implementing modules should get one of these by a QI
from an nsICommandManager.
*/
[scriptable, uuid(35e474ae-8016-4c34-9644-edc11f8b0ce1)]
interface nsPICommandUpdater : nsISupports
{
/*
* Init the command updater, passing an nsIDOMWindow which
* is the window that the command updater lives on.
*
*/
void init(in mozIDOMWindowProxy aWindow);
/*
* Notify the command manager that the status of a command
* changed. It may have changed from enabled to disabled,
* or vice versa, or become toggled etc.
*/
void commandStatusChanged(in string aCommandName);
};

View file

@ -0,0 +1,19 @@
# -*- 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/.
XPIDL_SOURCES += [
'nsIFind.idl',
'nsIWebBrowserFind.idl',
]
XPIDL_MODULE = 'find'
UNIFIED_SOURCES += [
'nsFind.cpp',
'nsWebBrowserFind.cpp',
]
FINAL_LIBRARY = 'xul'

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,83 @@
/* -*- 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 nsFind_h__
#define nsFind_h__
#include "nsIFind.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMNode.h"
#include "nsIDOMRange.h"
#include "nsIContentIterator.h"
#include "nsIWordBreaker.h"
class nsIContent;
#define NS_FIND_CONTRACTID "@mozilla.org/embedcomp/rangefind;1"
#define NS_FIND_CID \
{0x471f4944, 0x1dd2, 0x11b2, {0x87, 0xac, 0x90, 0xbe, 0x0a, 0x51, 0xd6, 0x09}}
class nsFindContentIterator;
class nsFind : public nsIFind
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIFIND
NS_DECL_CYCLE_COLLECTION_CLASS(nsFind)
nsFind();
protected:
virtual ~nsFind();
// Parameters set from the interface:
//nsCOMPtr<nsIDOMRange> mRange; // search only in this range
bool mFindBackward;
bool mCaseSensitive;
// Use "find entire words" mode by setting to a word breaker or null, to
// disable "entire words" mode.
nsCOMPtr<nsIWordBreaker> mWordBreaker;
int32_t mIterOffset;
nsCOMPtr<nsIDOMNode> mIterNode;
// Last block parent, so that we will notice crossing block boundaries:
nsCOMPtr<nsIDOMNode> mLastBlockParent;
nsresult GetBlockParent(nsIDOMNode* aNode, nsIDOMNode** aParent);
// Utility routines:
bool IsTextNode(nsIDOMNode* aNode);
bool IsBlockNode(nsIContent* aNode);
bool SkipNode(nsIContent* aNode);
bool IsVisibleNode(nsIDOMNode* aNode);
// Move in the right direction for our search:
nsresult NextNode(nsIDOMRange* aSearchRange,
nsIDOMRange* aStartPoint, nsIDOMRange* aEndPoint,
bool aContinueOk);
// Get the first character from the next node (last if mFindBackward).
char16_t PeekNextChar(nsIDOMRange* aSearchRange,
nsIDOMRange* aStartPoint,
nsIDOMRange* aEndPoint);
// Reset variables before returning -- don't hold any references.
void ResetAll();
// The iterator we use to move through the document:
nsresult InitIterator(nsIDOMNode* aStartNode, int32_t aStartOffset,
nsIDOMNode* aEndNode, int32_t aEndOffset);
RefPtr<nsFindContentIterator> mIterator;
friend class PeekNextCharRestoreState;
};
#endif // nsFind_h__

View file

@ -0,0 +1,34 @@
/* -*- Mode: C++; 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 nsIDOMRange;
interface nsIWordBreaker;
[scriptable, uuid(40aba110-2a56-4678-be90-e2c17a9ae7d7)]
interface nsIFind : nsISupports
{
attribute boolean findBackwards;
attribute boolean caseSensitive;
attribute boolean entireWord;
/**
* Find some text in the current context. The implementation is
* responsible for performing the find and highlighting the text.
*
* @param aPatText The text to search for.
* @param aSearchRange A Range specifying domain of search.
* @param aStartPoint A Range specifying search start point.
* If not collapsed, we'll start from
* end (forward) or start (backward).
* @param aEndPoint A Range specifying search end point.
* If not collapsed, we'll end at
* end (forward) or start (backward).
* @retval A range spanning the match that was found (or null).
*/
nsIDOMRange Find(in wstring aPatText, in nsIDOMRange aSearchRange,
in nsIDOMRange aStartPoint, in nsIDOMRange aEndPoint);
};

View file

@ -0,0 +1,145 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "domstubs.idl"
interface mozIDOMWindowProxy;
/* THIS IS A PUBLIC EMBEDDING API */
/**
* nsIWebBrowserFind
*
* Searches for text in a web browser.
*
* Get one by doing a GetInterface on an nsIWebBrowser.
*
* By default, the implementation will search the focussed frame, or
* if there is no focussed frame, the web browser content area. It
* does not by default search subframes or iframes. To change this
* behaviour, and to explicitly set the frame to search,
* QueryInterface to nsIWebBrowserFindInFrames.
*/
[scriptable, uuid(e4920136-b3e0-49e0-b1cd-6c783d2591a8)]
interface nsIWebBrowserFind : nsISupports
{
/**
* findNext
*
* Finds, highlights, and scrolls into view the next occurrence of the
* search string, using the current search settings. Fails if the
* search string is empty.
*
* @return Whether an occurrence was found
*/
boolean findNext();
/**
* searchString
*
* The string to search for. This must be non-empty to search.
*/
attribute wstring searchString;
/**
* findBackwards
*
* Whether to find backwards (towards the beginning of the document).
* Default is false (search forward).
*/
attribute boolean findBackwards;
/**
* wrapFind
*
* Whether the search wraps around to the start (or end) of the document
* if no match was found between the current position and the end (or
* beginning). Works correctly when searching backwards. Default is
* false.
*/
attribute boolean wrapFind;
/**
* entireWord
*
* Whether to match entire words only. Default is false.
*/
attribute boolean entireWord;
/**
* matchCase
*
* Whether to match case (case sensitive) when searching. Default is false.
*/
attribute boolean matchCase;
/**
* searchFrames
*
* Whether to search through all frames in the content area. Default is true.
*
* Note that you can control whether the search propagates into child or
* parent frames explicitly using nsIWebBrowserFindInFrames, but if one,
* but not both, of searchSubframes and searchParentFrames are set, this
* returns false.
*/
attribute boolean searchFrames;
};
/**
* nsIWebBrowserFindInFrames
*
* Controls how find behaves when multiple frames or iframes are present.
*
* Get by doing a QueryInterface from nsIWebBrowserFind.
*/
[scriptable, uuid(e0f5d182-34bc-11d5-be5b-b760676c6ebc)]
interface nsIWebBrowserFindInFrames : nsISupports
{
/**
* currentSearchFrame
*
* Frame at which to start the search. Once the search is done, this will
* be set to be the last frame searched, whether or not a result was found.
* Has to be equal to or contained within the rootSearchFrame.
*/
attribute mozIDOMWindowProxy currentSearchFrame;
/**
* rootSearchFrame
*
* Frame within which to confine the search (normally the content area frame).
* Set this to only search a subtree of the frame hierarchy.
*/
attribute mozIDOMWindowProxy rootSearchFrame;
/**
* searchSubframes
*
* Whether to recurse down into subframes while searching. Default is true.
*
* Setting nsIWebBrowserfind.searchFrames to true sets this to true.
*/
attribute boolean searchSubframes;
/**
* searchParentFrames
*
* Whether to allow the search to propagate out of the currentSearchFrame into its
* parent frame(s). Search is always confined within the rootSearchFrame. Default
* is true.
*
* Setting nsIWebBrowserfind.searchFrames to true sets this to true.
*/
attribute boolean searchParentFrames;
};

View file

@ -0,0 +1,868 @@
/* -*- 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 "nsWebBrowserFind.h"
// Only need this for NS_FIND_CONTRACTID,
// else we could use nsIDOMRange.h and nsIFind.h.
#include "nsFind.h"
#include "nsIComponentManager.h"
#include "nsIScriptSecurityManager.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsPIDOMWindow.h"
#include "nsIURI.h"
#include "nsIDocShell.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsISelectionController.h"
#include "nsISelection.h"
#include "nsIFrame.h"
#include "nsITextControlFrame.h"
#include "nsReadableUtils.h"
#include "nsIDOMHTMLElement.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIContent.h"
#include "nsContentCID.h"
#include "nsIServiceManager.h"
#include "nsIObserverService.h"
#include "nsISupportsPrimitives.h"
#include "nsFind.h"
#include "nsError.h"
#include "nsFocusManager.h"
#include "mozilla/Services.h"
#include "mozilla/dom/Element.h"
#include "nsISimpleEnumerator.h"
#include "nsContentUtils.h"
#if DEBUG
#include "nsIWebNavigation.h"
#include "nsXPIDLString.h"
#endif
nsWebBrowserFind::nsWebBrowserFind()
: mFindBackwards(false)
, mWrapFind(false)
, mEntireWord(false)
, mMatchCase(false)
, mSearchSubFrames(true)
, mSearchParentFrames(true)
{
}
nsWebBrowserFind::~nsWebBrowserFind()
{
}
NS_IMPL_ISUPPORTS(nsWebBrowserFind, nsIWebBrowserFind,
nsIWebBrowserFindInFrames)
NS_IMETHODIMP
nsWebBrowserFind::FindNext(bool* aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false;
NS_ENSURE_TRUE(CanFindNext(), NS_ERROR_NOT_INITIALIZED);
nsresult rv = NS_OK;
nsCOMPtr<nsPIDOMWindowOuter> searchFrame = do_QueryReferent(mCurrentSearchFrame);
NS_ENSURE_TRUE(searchFrame, NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<nsPIDOMWindowOuter> rootFrame = do_QueryReferent(mRootSearchFrame);
NS_ENSURE_TRUE(rootFrame, NS_ERROR_NOT_INITIALIZED);
// first, if there's a "cmd_findagain" observer around, check to see if it
// wants to perform the find again command . If it performs the find again
// it will return true, in which case we exit ::FindNext() early.
// Otherwise, nsWebBrowserFind needs to perform the find again command itself
// this is used by nsTypeAheadFind, which controls find again when it was
// the last executed find in the current window.
nsCOMPtr<nsIObserverService> observerSvc =
mozilla::services::GetObserverService();
if (observerSvc) {
nsCOMPtr<nsISupportsInterfacePointer> windowSupportsData =
do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> searchWindowSupports = do_QueryInterface(rootFrame);
windowSupportsData->SetData(searchWindowSupports);
NS_NAMED_LITERAL_STRING(dnStr, "down");
NS_NAMED_LITERAL_STRING(upStr, "up");
observerSvc->NotifyObservers(windowSupportsData,
"nsWebBrowserFind_FindAgain",
mFindBackwards ? upStr.get() : dnStr.get());
windowSupportsData->GetData(getter_AddRefs(searchWindowSupports));
// findnext performed if search window data cleared out
*aResult = searchWindowSupports == nullptr;
if (*aResult) {
return NS_OK;
}
}
// next, look in the current frame. If found, return.
// Beware! This may flush notifications via synchronous
// ScrollSelectionIntoView.
rv = SearchInFrame(searchFrame, false, aResult);
if (NS_FAILED(rv)) {
return rv;
}
if (*aResult) {
return OnFind(searchFrame); // we are done
}
// if we are not searching other frames, return
if (!mSearchSubFrames && !mSearchParentFrames) {
return NS_OK;
}
nsIDocShell* rootDocShell = rootFrame->GetDocShell();
if (!rootDocShell) {
return NS_ERROR_FAILURE;
}
int32_t enumDirection = mFindBackwards ? nsIDocShell::ENUMERATE_BACKWARDS :
nsIDocShell::ENUMERATE_FORWARDS;
nsCOMPtr<nsISimpleEnumerator> docShellEnumerator;
rv = rootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeAll,
enumDirection,
getter_AddRefs(docShellEnumerator));
if (NS_FAILED(rv)) {
return rv;
}
// remember where we started
nsCOMPtr<nsIDocShellTreeItem> startingItem =
do_QueryInterface(searchFrame->GetDocShell(), &rv);
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIDocShellTreeItem> curItem;
// XXX We should avoid searching in frameset documents here.
// We also need to honour mSearchSubFrames and mSearchParentFrames.
bool hasMore, doFind = false;
while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMore)) &&
hasMore) {
nsCOMPtr<nsISupports> curSupports;
rv = docShellEnumerator->GetNext(getter_AddRefs(curSupports));
if (NS_FAILED(rv)) {
break;
}
curItem = do_QueryInterface(curSupports, &rv);
if (NS_FAILED(rv)) {
break;
}
if (doFind) {
searchFrame = curItem->GetWindow();
if (!searchFrame) {
break;
}
OnStartSearchFrame(searchFrame);
// Beware! This may flush notifications via synchronous
// ScrollSelectionIntoView.
rv = SearchInFrame(searchFrame, false, aResult);
if (NS_FAILED(rv)) {
return rv;
}
if (*aResult) {
return OnFind(searchFrame); // we are done
}
OnEndSearchFrame(searchFrame);
}
if (curItem.get() == startingItem.get()) {
doFind = true; // start looking in frames after this one
}
}
if (!mWrapFind) {
// remember where we left off
SetCurrentSearchFrame(searchFrame);
return NS_OK;
}
// From here on, we're wrapping, first through the other frames, then finally
// from the beginning of the starting frame back to the starting point.
// because nsISimpleEnumerator is totally lame and isn't resettable, I have to
// make a new one
docShellEnumerator = nullptr;
rv = rootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeAll,
enumDirection,
getter_AddRefs(docShellEnumerator));
if (NS_FAILED(rv)) {
return rv;
}
while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMore)) &&
hasMore) {
nsCOMPtr<nsISupports> curSupports;
rv = docShellEnumerator->GetNext(getter_AddRefs(curSupports));
if (NS_FAILED(rv)) {
break;
}
curItem = do_QueryInterface(curSupports, &rv);
if (NS_FAILED(rv)) {
break;
}
searchFrame = curItem->GetWindow();
if (!searchFrame) {
rv = NS_ERROR_FAILURE;
break;
}
if (curItem.get() == startingItem.get()) {
// Beware! This may flush notifications via synchronous
// ScrollSelectionIntoView.
rv = SearchInFrame(searchFrame, true, aResult);
if (NS_FAILED(rv)) {
return rv;
}
if (*aResult) {
return OnFind(searchFrame); // we are done
}
break;
}
OnStartSearchFrame(searchFrame);
// Beware! This may flush notifications via synchronous
// ScrollSelectionIntoView.
rv = SearchInFrame(searchFrame, false, aResult);
if (NS_FAILED(rv)) {
return rv;
}
if (*aResult) {
return OnFind(searchFrame); // we are done
}
OnEndSearchFrame(searchFrame);
}
// remember where we left off
SetCurrentSearchFrame(searchFrame);
NS_ASSERTION(NS_SUCCEEDED(rv), "Something failed");
return rv;
}
NS_IMETHODIMP
nsWebBrowserFind::GetSearchString(char16_t** aSearchString)
{
NS_ENSURE_ARG_POINTER(aSearchString);
*aSearchString = ToNewUnicode(mSearchString);
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::SetSearchString(const char16_t* aSearchString)
{
mSearchString.Assign(aSearchString);
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::GetFindBackwards(bool* aFindBackwards)
{
NS_ENSURE_ARG_POINTER(aFindBackwards);
*aFindBackwards = mFindBackwards;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::SetFindBackwards(bool aFindBackwards)
{
mFindBackwards = aFindBackwards;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::GetWrapFind(bool* aWrapFind)
{
NS_ENSURE_ARG_POINTER(aWrapFind);
*aWrapFind = mWrapFind;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::SetWrapFind(bool aWrapFind)
{
mWrapFind = aWrapFind;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::GetEntireWord(bool* aEntireWord)
{
NS_ENSURE_ARG_POINTER(aEntireWord);
*aEntireWord = mEntireWord;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::SetEntireWord(bool aEntireWord)
{
mEntireWord = aEntireWord;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::GetMatchCase(bool* aMatchCase)
{
NS_ENSURE_ARG_POINTER(aMatchCase);
*aMatchCase = mMatchCase;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::SetMatchCase(bool aMatchCase)
{
mMatchCase = aMatchCase;
return NS_OK;
}
static bool
IsInNativeAnonymousSubtree(nsIContent* aContent)
{
while (aContent) {
nsIContent* bindingParent = aContent->GetBindingParent();
if (bindingParent == aContent) {
return true;
}
aContent = bindingParent;
}
return false;
}
void
nsWebBrowserFind::SetSelectionAndScroll(nsPIDOMWindowOuter* aWindow,
nsIDOMRange* aRange)
{
nsCOMPtr<nsIDocument> doc = aWindow->GetDoc();
if (!doc) {
return;
}
nsIPresShell* presShell = doc->GetShell();
if (!presShell) {
return;
}
nsCOMPtr<nsIDOMNode> node;
aRange->GetStartContainer(getter_AddRefs(node));
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
nsIFrame* frame = content->GetPrimaryFrame();
if (!frame) {
return;
}
nsCOMPtr<nsISelectionController> selCon;
frame->GetSelectionController(presShell->GetPresContext(),
getter_AddRefs(selCon));
// since the match could be an anonymous textnode inside a
// <textarea> or text <input>, we need to get the outer frame
nsITextControlFrame* tcFrame = nullptr;
for (; content; content = content->GetParent()) {
if (!IsInNativeAnonymousSubtree(content)) {
nsIFrame* f = content->GetPrimaryFrame();
if (!f) {
return;
}
tcFrame = do_QueryFrame(f);
break;
}
}
nsCOMPtr<nsISelection> selection;
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(selection));
if (selection) {
selection->RemoveAllRanges();
selection->AddRange(aRange);
nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
if (fm) {
if (tcFrame) {
nsCOMPtr<nsIDOMElement> newFocusedElement(do_QueryInterface(content));
fm->SetFocus(newFocusedElement, nsIFocusManager::FLAG_NOSCROLL);
} else {
nsCOMPtr<nsIDOMElement> result;
fm->MoveFocus(aWindow, nullptr, nsIFocusManager::MOVEFOCUS_CARET,
nsIFocusManager::FLAG_NOSCROLL, getter_AddRefs(result));
}
}
// Scroll if necessary to make the selection visible:
// Must be the last thing to do - bug 242056
// After ScrollSelectionIntoView(), the pending notifications might be
// flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
selCon->ScrollSelectionIntoView(
nsISelectionController::SELECTION_NORMAL,
nsISelectionController::SELECTION_WHOLE_SELECTION,
nsISelectionController::SCROLL_CENTER_VERTICALLY |
nsISelectionController::SCROLL_SYNCHRONOUS);
}
}
// Adapted from nsTextServicesDocument::GetDocumentContentRootNode
nsresult
nsWebBrowserFind::GetRootNode(nsIDOMDocument* aDomDoc, nsIDOMNode** aNode)
{
nsresult rv;
NS_ENSURE_ARG_POINTER(aNode);
*aNode = 0;
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(aDomDoc);
if (htmlDoc) {
// For HTML documents, the content root node is the body.
nsCOMPtr<nsIDOMHTMLElement> bodyElement;
rv = htmlDoc->GetBody(getter_AddRefs(bodyElement));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_ARG_POINTER(bodyElement);
bodyElement.forget(aNode);
return NS_OK;
}
// For non-HTML documents, the content root node will be the doc element.
nsCOMPtr<nsIDOMElement> docElement;
rv = aDomDoc->GetDocumentElement(getter_AddRefs(docElement));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_ARG_POINTER(docElement);
docElement.forget(aNode);
return NS_OK;
}
nsresult
nsWebBrowserFind::SetRangeAroundDocument(nsIDOMRange* aSearchRange,
nsIDOMRange* aStartPt,
nsIDOMRange* aEndPt,
nsIDOMDocument* aDoc)
{
nsCOMPtr<nsIDOMNode> bodyNode;
nsresult rv = GetRootNode(aDoc, getter_AddRefs(bodyNode));
nsCOMPtr<nsIContent> bodyContent(do_QueryInterface(bodyNode));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_ARG_POINTER(bodyContent);
uint32_t childCount = bodyContent->GetChildCount();
aSearchRange->SetStart(bodyNode, 0);
aSearchRange->SetEnd(bodyNode, childCount);
if (mFindBackwards) {
aStartPt->SetStart(bodyNode, childCount);
aStartPt->SetEnd(bodyNode, childCount);
aEndPt->SetStart(bodyNode, 0);
aEndPt->SetEnd(bodyNode, 0);
} else {
aStartPt->SetStart(bodyNode, 0);
aStartPt->SetEnd(bodyNode, 0);
aEndPt->SetStart(bodyNode, childCount);
aEndPt->SetEnd(bodyNode, childCount);
}
return NS_OK;
}
// Set the range to go from the end of the current selection to the end of the
// document (forward), or beginning to beginning (reverse). or around the whole
// document if there's no selection.
nsresult
nsWebBrowserFind::GetSearchLimits(nsIDOMRange* aSearchRange,
nsIDOMRange* aStartPt, nsIDOMRange* aEndPt,
nsIDOMDocument* aDoc, nsISelection* aSel,
bool aWrap)
{
NS_ENSURE_ARG_POINTER(aSel);
// There is a selection.
int32_t count = -1;
nsresult rv = aSel->GetRangeCount(&count);
NS_ENSURE_SUCCESS(rv, rv);
if (count < 1) {
return SetRangeAroundDocument(aSearchRange, aStartPt, aEndPt, aDoc);
}
// Need bodyNode, for the start/end of the document
nsCOMPtr<nsIDOMNode> bodyNode;
rv = GetRootNode(aDoc, getter_AddRefs(bodyNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> bodyContent(do_QueryInterface(bodyNode));
NS_ENSURE_ARG_POINTER(bodyContent);
uint32_t childCount = bodyContent->GetChildCount();
// There are four possible range endpoints we might use:
// DocumentStart, SelectionStart, SelectionEnd, DocumentEnd.
nsCOMPtr<nsIDOMRange> range;
nsCOMPtr<nsIDOMNode> node;
int32_t offset;
// Forward, not wrapping: SelEnd to DocEnd
if (!mFindBackwards && !aWrap) {
// This isn't quite right, since the selection's ranges aren't
// necessarily in order; but they usually will be.
aSel->GetRangeAt(count - 1, getter_AddRefs(range));
if (!range) {
return NS_ERROR_UNEXPECTED;
}
range->GetEndContainer(getter_AddRefs(node));
if (!node) {
return NS_ERROR_UNEXPECTED;
}
range->GetEndOffset(&offset);
aSearchRange->SetStart(node, offset);
aSearchRange->SetEnd(bodyNode, childCount);
aStartPt->SetStart(node, offset);
aStartPt->SetEnd(node, offset);
aEndPt->SetStart(bodyNode, childCount);
aEndPt->SetEnd(bodyNode, childCount);
}
// Backward, not wrapping: DocStart to SelStart
else if (mFindBackwards && !aWrap) {
aSel->GetRangeAt(0, getter_AddRefs(range));
if (!range) {
return NS_ERROR_UNEXPECTED;
}
range->GetStartContainer(getter_AddRefs(node));
if (!node) {
return NS_ERROR_UNEXPECTED;
}
range->GetStartOffset(&offset);
aSearchRange->SetStart(bodyNode, 0);
aSearchRange->SetEnd(bodyNode, childCount);
aStartPt->SetStart(node, offset);
aStartPt->SetEnd(node, offset);
aEndPt->SetStart(bodyNode, 0);
aEndPt->SetEnd(bodyNode, 0);
}
// Forward, wrapping: DocStart to SelEnd
else if (!mFindBackwards && aWrap) {
aSel->GetRangeAt(count - 1, getter_AddRefs(range));
if (!range) {
return NS_ERROR_UNEXPECTED;
}
range->GetEndContainer(getter_AddRefs(node));
if (!node) {
return NS_ERROR_UNEXPECTED;
}
range->GetEndOffset(&offset);
aSearchRange->SetStart(bodyNode, 0);
aSearchRange->SetEnd(bodyNode, childCount);
aStartPt->SetStart(bodyNode, 0);
aStartPt->SetEnd(bodyNode, 0);
aEndPt->SetStart(node, offset);
aEndPt->SetEnd(node, offset);
}
// Backward, wrapping: SelStart to DocEnd
else if (mFindBackwards && aWrap) {
aSel->GetRangeAt(0, getter_AddRefs(range));
if (!range) {
return NS_ERROR_UNEXPECTED;
}
range->GetStartContainer(getter_AddRefs(node));
if (!node) {
return NS_ERROR_UNEXPECTED;
}
range->GetStartOffset(&offset);
aSearchRange->SetStart(bodyNode, 0);
aSearchRange->SetEnd(bodyNode, childCount);
aStartPt->SetStart(bodyNode, childCount);
aStartPt->SetEnd(bodyNode, childCount);
aEndPt->SetStart(node, offset);
aEndPt->SetEnd(node, offset);
}
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::GetSearchFrames(bool* aSearchFrames)
{
NS_ENSURE_ARG_POINTER(aSearchFrames);
// this only returns true if we are searching both sub and parent frames.
// There is ambiguity if the caller has previously set one, but not both of
// these.
*aSearchFrames = mSearchSubFrames && mSearchParentFrames;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::SetSearchFrames(bool aSearchFrames)
{
mSearchSubFrames = aSearchFrames;
mSearchParentFrames = aSearchFrames;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::GetCurrentSearchFrame(mozIDOMWindowProxy** aCurrentSearchFrame)
{
NS_ENSURE_ARG_POINTER(aCurrentSearchFrame);
nsCOMPtr<mozIDOMWindowProxy> searchFrame = do_QueryReferent(mCurrentSearchFrame);
searchFrame.forget(aCurrentSearchFrame);
return (*aCurrentSearchFrame) ? NS_OK : NS_ERROR_NOT_INITIALIZED;
}
NS_IMETHODIMP
nsWebBrowserFind::SetCurrentSearchFrame(mozIDOMWindowProxy* aCurrentSearchFrame)
{
// is it ever valid to set this to null?
NS_ENSURE_ARG(aCurrentSearchFrame);
mCurrentSearchFrame = do_GetWeakReference(aCurrentSearchFrame);
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::GetRootSearchFrame(mozIDOMWindowProxy** aRootSearchFrame)
{
NS_ENSURE_ARG_POINTER(aRootSearchFrame);
nsCOMPtr<mozIDOMWindowProxy> searchFrame = do_QueryReferent(mRootSearchFrame);
searchFrame.forget(aRootSearchFrame);
return (*aRootSearchFrame) ? NS_OK : NS_ERROR_NOT_INITIALIZED;
}
NS_IMETHODIMP
nsWebBrowserFind::SetRootSearchFrame(mozIDOMWindowProxy* aRootSearchFrame)
{
// is it ever valid to set this to null?
NS_ENSURE_ARG(aRootSearchFrame);
mRootSearchFrame = do_GetWeakReference(aRootSearchFrame);
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::GetSearchSubframes(bool* aSearchSubframes)
{
NS_ENSURE_ARG_POINTER(aSearchSubframes);
*aSearchSubframes = mSearchSubFrames;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::SetSearchSubframes(bool aSearchSubframes)
{
mSearchSubFrames = aSearchSubframes;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::GetSearchParentFrames(bool* aSearchParentFrames)
{
NS_ENSURE_ARG_POINTER(aSearchParentFrames);
*aSearchParentFrames = mSearchParentFrames;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowserFind::SetSearchParentFrames(bool aSearchParentFrames)
{
mSearchParentFrames = aSearchParentFrames;
return NS_OK;
}
/*
This method handles finding in a single window (aka frame).
*/
nsresult
nsWebBrowserFind::SearchInFrame(nsPIDOMWindowOuter* aWindow, bool aWrapping,
bool* aDidFind)
{
NS_ENSURE_ARG(aWindow);
NS_ENSURE_ARG_POINTER(aDidFind);
*aDidFind = false;
// Do security check, to ensure that the frame we're searching is
// acccessible from the frame where the Find is being run.
// get a uri for the window
nsCOMPtr<nsIDocument> theDoc = aWindow->GetDoc();
if (!theDoc) {
return NS_ERROR_FAILURE;
}
if (!nsContentUtils::SubjectPrincipal()->Subsumes(theDoc->NodePrincipal())) {
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
nsresult rv;
nsCOMPtr<nsIFind> find = do_CreateInstance(NS_FIND_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
(void)find->SetCaseSensitive(mMatchCase);
(void)find->SetFindBackwards(mFindBackwards);
(void)find->SetEntireWord(mEntireWord);
// Now make sure the content (for actual finding) and frame (for
// selection) models are up to date.
theDoc->FlushPendingNotifications(Flush_Frames);
nsCOMPtr<nsISelection> sel = GetFrameSelection(aWindow);
NS_ENSURE_ARG_POINTER(sel);
nsCOMPtr<nsIDOMRange> searchRange = new nsRange(theDoc);
NS_ENSURE_ARG_POINTER(searchRange);
nsCOMPtr<nsIDOMRange> startPt = new nsRange(theDoc);
NS_ENSURE_ARG_POINTER(startPt);
nsCOMPtr<nsIDOMRange> endPt = new nsRange(theDoc);
NS_ENSURE_ARG_POINTER(endPt);
nsCOMPtr<nsIDOMRange> foundRange;
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(theDoc);
MOZ_ASSERT(domDoc);
// If !aWrapping, search from selection to end
if (!aWrapping)
rv = GetSearchLimits(searchRange, startPt, endPt, domDoc, sel, false);
// If aWrapping, search the part of the starting frame
// up to the point where we left off.
else
rv = GetSearchLimits(searchRange, startPt, endPt, domDoc, sel, true);
NS_ENSURE_SUCCESS(rv, rv);
rv = find->Find(mSearchString.get(), searchRange, startPt, endPt,
getter_AddRefs(foundRange));
if (NS_SUCCEEDED(rv) && foundRange) {
*aDidFind = true;
sel->RemoveAllRanges();
// Beware! This may flush notifications via synchronous
// ScrollSelectionIntoView.
SetSelectionAndScroll(aWindow, foundRange);
}
return rv;
}
// called when we start searching a frame that is not the initial focussed
// frame. Prepare the frame to be searched. we clear the selection, so that the
// search starts from the top of the frame.
nsresult
nsWebBrowserFind::OnStartSearchFrame(nsPIDOMWindowOuter* aWindow)
{
return ClearFrameSelection(aWindow);
}
// called when we are done searching a frame and didn't find anything, and about
// about to start searching the next frame.
nsresult
nsWebBrowserFind::OnEndSearchFrame(nsPIDOMWindowOuter* aWindow)
{
return NS_OK;
}
already_AddRefed<nsISelection>
nsWebBrowserFind::GetFrameSelection(nsPIDOMWindowOuter* aWindow)
{
nsCOMPtr<nsIDocument> doc = aWindow->GetDoc();
if (!doc) {
return nullptr;
}
nsIPresShell* presShell = doc->GetShell();
if (!presShell) {
return nullptr;
}
// text input controls have their independent selection controllers that we
// must use when they have focus.
nsPresContext* presContext = presShell->GetPresContext();
nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
nsCOMPtr<nsIContent> focusedContent = nsFocusManager::GetFocusedDescendant(
aWindow, false, getter_AddRefs(focusedWindow));
nsIFrame* frame =
focusedContent ? focusedContent->GetPrimaryFrame() : nullptr;
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> sel;
if (frame) {
frame->GetSelectionController(presContext, getter_AddRefs(selCon));
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(sel));
if (sel) {
int32_t count = -1;
sel->GetRangeCount(&count);
if (count > 0) {
return sel.forget();
}
}
}
selCon = do_QueryInterface(presShell);
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(sel));
return sel.forget();
}
nsresult
nsWebBrowserFind::ClearFrameSelection(nsPIDOMWindowOuter* aWindow)
{
NS_ENSURE_ARG(aWindow);
nsCOMPtr<nsISelection> selection = GetFrameSelection(aWindow);
if (selection) {
selection->RemoveAllRanges();
}
return NS_OK;
}
nsresult
nsWebBrowserFind::OnFind(nsPIDOMWindowOuter* aFoundWindow)
{
SetCurrentSearchFrame(aFoundWindow);
// We don't want a selection to appear in two frames simultaneously
nsCOMPtr<nsPIDOMWindowOuter> lastFocusedWindow =
do_QueryReferent(mLastFocusedWindow);
if (lastFocusedWindow && lastFocusedWindow != aFoundWindow) {
ClearFrameSelection(lastFocusedWindow);
}
nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
if (fm) {
// get the containing frame and focus it. For top-level windows, the right
// window should already be focused.
nsCOMPtr<nsIDOMElement> frameElement =
do_QueryInterface(aFoundWindow->GetFrameElementInternal());
if (frameElement) {
fm->SetFocus(frameElement, 0);
}
mLastFocusedWindow = do_GetWeakReference(aFoundWindow);
}
return NS_OK;
}

View file

@ -0,0 +1,95 @@
/* -*- 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 nsWebBrowserFindImpl_h__
#define nsWebBrowserFindImpl_h__
#include "nsIWebBrowserFind.h"
#include "nsCOMPtr.h"
#include "nsWeakReference.h"
#include "nsIFind.h"
#include "nsString.h"
#define NS_WEB_BROWSER_FIND_CONTRACTID "@mozilla.org/embedcomp/find;1"
#define NS_WEB_BROWSER_FIND_CID \
{0x57cf9383, 0x3405, 0x11d5, {0xbe, 0x5b, 0xaa, 0x20, 0xfa, 0x2c, 0xf3, 0x7c}}
class nsISelection;
class nsIDOMWindow;
class nsIDocShell;
//*****************************************************************************
// class nsWebBrowserFind
//*****************************************************************************
class nsWebBrowserFind
: public nsIWebBrowserFind
, public nsIWebBrowserFindInFrames
{
public:
nsWebBrowserFind();
// nsISupports
NS_DECL_ISUPPORTS
// nsIWebBrowserFind
NS_DECL_NSIWEBBROWSERFIND
// nsIWebBrowserFindInFrames
NS_DECL_NSIWEBBROWSERFINDINFRAMES
protected:
virtual ~nsWebBrowserFind();
bool CanFindNext() { return mSearchString.Length() != 0; }
nsresult SearchInFrame(nsPIDOMWindowOuter* aWindow, bool aWrapping,
bool* aDidFind);
nsresult OnStartSearchFrame(nsPIDOMWindowOuter* aWindow);
nsresult OnEndSearchFrame(nsPIDOMWindowOuter* aWindow);
already_AddRefed<nsISelection> GetFrameSelection(nsPIDOMWindowOuter* aWindow);
nsresult ClearFrameSelection(nsPIDOMWindowOuter* aWindow);
nsresult OnFind(nsPIDOMWindowOuter* aFoundWindow);
void SetSelectionAndScroll(nsPIDOMWindowOuter* aWindow, nsIDOMRange* aRange);
nsresult GetRootNode(nsIDOMDocument* aDomDoc, nsIDOMNode** aNode);
nsresult GetSearchLimits(nsIDOMRange* aRange,
nsIDOMRange* aStartPt, nsIDOMRange* aEndPt,
nsIDOMDocument* aDoc, nsISelection* aSel,
bool aWrap);
nsresult SetRangeAroundDocument(nsIDOMRange* aSearchRange,
nsIDOMRange* aStartPoint,
nsIDOMRange* aEndPoint,
nsIDOMDocument* aDoc);
protected:
nsString mSearchString;
bool mFindBackwards;
bool mWrapFind;
bool mEntireWord;
bool mMatchCase;
bool mSearchSubFrames;
bool mSearchParentFrames;
// These are all weak because who knows if windows can go away during our
// lifetime.
nsWeakPtr mCurrentSearchFrame;
nsWeakPtr mRootSearchFrame;
nsWeakPtr mLastFocusedWindow;
};
#endif

View file

@ -0,0 +1,20 @@
# -*- 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/.
# You'd think we could skip building ui if XUL is disabled,
# but we need to export interface headers from those directories.
DIRS += [
'windowwatcher',
'appstartup',
'find',
'webbrowserpersist',
'commandhandler',
]
if CONFIG['MOZ_XUL']:
DIRS += ['printingui']
DIRS += ['build']

View file

@ -0,0 +1,35 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* 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 protocol PPrinting;
namespace mozilla {
namespace embedding {
protocol PPrintProgressDialog
{
manager PPrinting;
parent:
async StateChange(long stateFlags,
nsresult status);
async ProgressChange(long curSelfProgress,
long maxSelfProgress,
long curTotalProgress,
long maxTotalProgress);
async DocTitleChange(nsString newTitle);
async DocURLChange(nsString newURL);
async __delete__();
child:
async DialogOpened();
};
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,29 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* 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 PPrintingTypes;
include protocol PPrinting;
include protocol PRemotePrintJob;
namespace mozilla {
namespace embedding {
// A PrintData for success, a failure nsresult for failure.
union PrintDataOrNSResult
{
PrintData;
nsresult;
};
protocol PPrintSettingsDialog
{
manager PPrinting;
child:
async __delete__(PrintDataOrNSResult result);
};
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,48 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* 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 PPrintingTypes;
include protocol PContent;
include protocol PBrowser;
include protocol PPrintProgressDialog;
include protocol PPrintSettingsDialog;
include protocol PRemotePrintJob;
namespace mozilla {
namespace embedding {
sync protocol PPrinting
{
manager PContent;
manages PPrintProgressDialog;
manages PPrintSettingsDialog;
manages PRemotePrintJob;
parent:
sync ShowProgress(PBrowser browser,
PPrintProgressDialog printProgressDialog,
nullable PRemotePrintJob remotePrintJob,
bool isForPrinting)
returns(bool notifyOnOpen,
nsresult rv);
async ShowPrintDialog(PPrintSettingsDialog dialog,
nullable PBrowser browser,
PrintData settings);
async PPrintProgressDialog();
async PPrintSettingsDialog();
sync SavePrintSettings(PrintData settings, bool usePrinterNamePrefix,
uint32_t flags)
returns(nsresult rv);
child:
async PRemotePrintJob();
async __delete__();
};
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,126 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* 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 protocol PRemotePrintJob;
namespace mozilla {
namespace embedding {
struct CStringKeyValue {
nsCString key;
nsCString value;
};
struct PrintData {
nullable PRemotePrintJob remotePrintJob;
int32_t startPageRange;
int32_t endPageRange;
double edgeTop;
double edgeLeft;
double edgeBottom;
double edgeRight;
double marginTop;
double marginLeft;
double marginBottom;
double marginRight;
double unwriteableMarginTop;
double unwriteableMarginLeft;
double unwriteableMarginBottom;
double unwriteableMarginRight;
double scaling;
bool printBGColors;
bool printBGImages;
short printRange;
nsString title;
nsString docURL;
nsString headerStrLeft;
nsString headerStrCenter;
nsString headerStrRight;
nsString footerStrLeft;
nsString footerStrCenter;
nsString footerStrRight;
short howToEnableFrameUI;
bool isCancelled;
short printFrameTypeUsage;
short printFrameType;
bool printSilent;
bool shrinkToFit;
bool showPrintProgress;
nsString paperName;
short paperData;
double paperWidth;
double paperHeight;
short paperSizeUnit;
bool printReversed;
bool printInColor;
int32_t orientation;
int32_t numCopies;
nsString printerName;
bool printToFile;
nsString toFileName;
short outputFormat;
int32_t printPageDelay;
int32_t resolution;
int32_t duplex;
bool isInitializedFromPrinter;
bool isInitializedFromPrefs;
int32_t optionFlags;
/* Windows-specific things */
nsString driverName;
nsString deviceName;
double printableWidthInInches;
double printableHeightInInches;
bool isFramesetDocument;
bool isFramesetFrameSelected;
bool isIFrameSelected;
bool isRangeSelection;
uint8_t[] devModeData;
/**
* GTK-specific things. Some of these might look like dupes of the
* information we're already passing, but the generalized settings that
* we hold in nsIPrintSettings don't map perfectly to GTK's GtkPrintSettings,
* so there are some nuances. GtkPrintSettings, for example, stores both an
* internal name for paper size, as well as the display name.
*/
CStringKeyValue[] GTKPrintSettings;
/**
* OS X specific things.
*/
nsString printJobName;
bool printAllPages;
bool mustCollate;
nsString disposition;
/** TODO: Is there an "unsigned short" primitive? **/
short pagesAcross;
short pagesDown;
double printTime;
bool detailedErrorReporting;
nsString faxNumber;
bool addHeaderAndFooter;
bool fileNameExtensionHidden;
/*
* Holds the scaling factor from the Print dialog when shrink
* to fit is not used. This is needed by the child when it
* isn't using remote printing. When shrink to fit is enabled
* (default), print dialog code ensures this value is 1.0.
*/
float scalingFactor;
/*
* Scaling factor for converting from OS X native paper size
* units to inches.
*/
float widthScale;
float heightScale;
double adjustedPaperWidth;
double adjustedPaperHeight;
};
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,158 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et 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 "PrintDataUtils.h"
#include "nsIPrintSettings.h"
#include "nsIServiceManager.h"
#include "nsIWebBrowserPrint.h"
#include "nsXPIDLString.h"
namespace mozilla {
namespace embedding {
/**
* MockWebBrowserPrint is a mostly useless implementation of nsIWebBrowserPrint,
* but wraps a PrintData so that it's able to return information to print
* settings dialogs that need an nsIWebBrowserPrint to interrogate.
*/
NS_IMPL_ISUPPORTS(MockWebBrowserPrint, nsIWebBrowserPrint);
MockWebBrowserPrint::MockWebBrowserPrint(const PrintData &aData)
: mData(aData)
{
MOZ_COUNT_CTOR(MockWebBrowserPrint);
}
MockWebBrowserPrint::~MockWebBrowserPrint()
{
MOZ_COUNT_DTOR(MockWebBrowserPrint);
}
NS_IMETHODIMP
MockWebBrowserPrint::GetGlobalPrintSettings(nsIPrintSettings **aGlobalPrintSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetCurrentPrintSettings(nsIPrintSettings **aCurrentPrintSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetCurrentChildDOMWindow(mozIDOMWindowProxy **aCurrentPrintSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetDoingPrint(bool *aDoingPrint)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetDoingPrintPreview(bool *aDoingPrintPreview)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetIsFramesetDocument(bool *aIsFramesetDocument)
{
*aIsFramesetDocument = mData.isFramesetDocument();
return NS_OK;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetIsFramesetFrameSelected(bool *aIsFramesetFrameSelected)
{
*aIsFramesetFrameSelected = mData.isFramesetFrameSelected();
return NS_OK;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetIsIFrameSelected(bool *aIsIFrameSelected)
{
*aIsIFrameSelected = mData.isIFrameSelected();
return NS_OK;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetIsRangeSelection(bool *aIsRangeSelection)
{
*aIsRangeSelection = mData.isRangeSelection();
return NS_OK;
}
NS_IMETHODIMP
MockWebBrowserPrint::GetPrintPreviewNumPages(int32_t *aPrintPreviewNumPages)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::Print(nsIPrintSettings* aThePrintSettings,
nsIWebProgressListener* aWPListener)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::PrintPreview(nsIPrintSettings* aThePrintSettings,
mozIDOMWindowProxy* aChildDOMWin,
nsIWebProgressListener* aWPListener)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::PrintPreviewNavigate(int16_t aNavType,
int32_t aPageNum)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::Cancel()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MockWebBrowserPrint::EnumerateDocumentNames(uint32_t* aCount,
char16_t*** aResult)
{
*aCount = 0;
*aResult = nullptr;
if (mData.printJobName().IsEmpty()) {
return NS_OK;
}
// The only consumer that cares about this is the OS X printing
// dialog, and even then, it only cares about the first document
// name. That's why we only send a single document name through
// PrintData.
char16_t** array = (char16_t**) moz_xmalloc(sizeof(char16_t*));
array[0] = ToNewUnicode(mData.printJobName());
*aCount = 1;
*aResult = array;
return NS_OK;
}
NS_IMETHODIMP
MockWebBrowserPrint::ExitPrintPreview()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et 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 mozilla_embedding_PrintDataUtils_h
#define mozilla_embedding_PrintDataUtils_h
#include "mozilla/embedding/PPrinting.h"
#include "nsIWebBrowserPrint.h"
/**
* nsIPrintSettings and nsIWebBrowserPrint information is sent back and forth
* across PPrinting via the PrintData struct. These are utilities for
* manipulating PrintData that can be used on either side of the communications
* channel.
*/
namespace mozilla {
namespace embedding {
class MockWebBrowserPrint final : public nsIWebBrowserPrint
{
public:
explicit MockWebBrowserPrint(const PrintData &aData);
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBBROWSERPRINT
private:
~MockWebBrowserPrint();
PrintData mData;
};
} // namespace embedding
} // namespace mozilla
#endif

View file

@ -0,0 +1,132 @@
/* 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/Unused.h"
#include "nsIObserver.h"
#include "PrintProgressDialogChild.h"
class nsIWebProgress;
class nsIRequest;
using mozilla::Unused;
namespace mozilla {
namespace embedding {
NS_IMPL_ISUPPORTS(PrintProgressDialogChild,
nsIWebProgressListener,
nsIPrintProgressParams)
PrintProgressDialogChild::PrintProgressDialogChild(
nsIObserver* aOpenObserver) :
mOpenObserver(aOpenObserver)
{
MOZ_COUNT_CTOR(PrintProgressDialogChild);
}
PrintProgressDialogChild::~PrintProgressDialogChild()
{
// When the printing engine stops supplying information about printing
// progress, it'll drop references to us and destroy us. We need to signal
// the parent to decrement its refcount, as well as prevent it from attempting
// to contact us further.
Unused << Send__delete__(this);
MOZ_COUNT_DTOR(PrintProgressDialogChild);
}
bool
PrintProgressDialogChild::RecvDialogOpened()
{
// nsPrintEngine's observer, which we're reporting to here, doesn't care
// what gets passed as the subject, topic or data, so we'll just send
// nullptrs.
mOpenObserver->Observe(nullptr, nullptr, nullptr);
return true;
}
// nsIWebProgressListener
NS_IMETHODIMP
PrintProgressDialogChild::OnStateChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
uint32_t aStateFlags,
nsresult aStatus)
{
Unused << SendStateChange(aStateFlags, aStatus);
return NS_OK;
}
NS_IMETHODIMP
PrintProgressDialogChild::OnProgressChange(nsIWebProgress * aProgress,
nsIRequest * aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
{
Unused << SendProgressChange(aCurSelfProgress, aMaxSelfProgress,
aCurTotalProgress, aMaxTotalProgress);
return NS_OK;
}
NS_IMETHODIMP
PrintProgressDialogChild::OnLocationChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
nsIURI* aURI,
uint32_t aFlags)
{
return NS_OK;
}
NS_IMETHODIMP
PrintProgressDialogChild::OnStatusChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aMessage)
{
return NS_OK;
}
NS_IMETHODIMP
PrintProgressDialogChild::OnSecurityChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
uint32_t aState)
{
return NS_OK;
}
// nsIPrintProgressParams
NS_IMETHODIMP PrintProgressDialogChild::GetDocTitle(char16_t* *aDocTitle)
{
NS_ENSURE_ARG(aDocTitle);
*aDocTitle = ToNewUnicode(mDocTitle);
return NS_OK;
}
NS_IMETHODIMP PrintProgressDialogChild::SetDocTitle(const char16_t* aDocTitle)
{
mDocTitle = aDocTitle;
Unused << SendDocTitleChange(nsString(aDocTitle));
return NS_OK;
}
NS_IMETHODIMP PrintProgressDialogChild::GetDocURL(char16_t **aDocURL)
{
NS_ENSURE_ARG(aDocURL);
*aDocURL = ToNewUnicode(mDocURL);
return NS_OK;
}
NS_IMETHODIMP PrintProgressDialogChild::SetDocURL(const char16_t* aDocURL)
{
mDocURL = aDocURL;
Unused << SendDocURLChange(nsString(aDocURL));
return NS_OK;
}
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,40 @@
/* 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 mozilla_embedding_PrintProgressDialogChild_h
#define mozilla_embedding_PrintProgressDialogChild_h
#include "mozilla/embedding/PPrintProgressDialogChild.h"
#include "nsIPrintProgressParams.h"
#include "nsIWebProgressListener.h"
class nsIObserver;
namespace mozilla {
namespace embedding {
class PrintProgressDialogChild final : public PPrintProgressDialogChild,
public nsIWebProgressListener,
public nsIPrintProgressParams
{
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSIPRINTPROGRESSPARAMS
public:
MOZ_IMPLICIT PrintProgressDialogChild(nsIObserver* aOpenObserver);
virtual bool RecvDialogOpened() override;
private:
virtual ~PrintProgressDialogChild();
nsCOMPtr<nsIObserver> mOpenObserver;
nsString mDocTitle;
nsString mDocURL;
};
} // namespace embedding
} // namespace mozilla
#endif

View file

@ -0,0 +1,113 @@
/* 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/Unused.h"
#include "nsIPrintProgressParams.h"
#include "nsIWebProgressListener.h"
#include "PrintProgressDialogParent.h"
using mozilla::Unused;
namespace mozilla {
namespace embedding {
NS_IMPL_ISUPPORTS(PrintProgressDialogParent, nsIObserver)
PrintProgressDialogParent::PrintProgressDialogParent() :
mActive(true)
{
MOZ_COUNT_CTOR(PrintProgressDialogParent);
}
PrintProgressDialogParent::~PrintProgressDialogParent()
{
MOZ_COUNT_DTOR(PrintProgressDialogParent);
}
void
PrintProgressDialogParent::SetWebProgressListener(nsIWebProgressListener* aListener)
{
mWebProgressListener = aListener;
}
void
PrintProgressDialogParent::SetPrintProgressParams(nsIPrintProgressParams* aParams)
{
mPrintProgressParams = aParams;
}
bool
PrintProgressDialogParent::RecvStateChange(const long& stateFlags,
const nsresult& status)
{
if (mWebProgressListener) {
mWebProgressListener->OnStateChange(nullptr, nullptr, stateFlags, status);
}
return true;
}
bool
PrintProgressDialogParent::RecvProgressChange(const long& curSelfProgress,
const long& maxSelfProgress,
const long& curTotalProgress,
const long& maxTotalProgress)
{
if (mWebProgressListener) {
mWebProgressListener->OnProgressChange(nullptr, nullptr, curSelfProgress,
maxSelfProgress, curTotalProgress,
maxTotalProgress);
}
return true;
}
bool
PrintProgressDialogParent::RecvDocTitleChange(const nsString& newTitle)
{
if (mPrintProgressParams) {
mPrintProgressParams->SetDocTitle(newTitle.get());
}
return true;
}
bool
PrintProgressDialogParent::RecvDocURLChange(const nsString& newURL)
{
if (mPrintProgressParams) {
mPrintProgressParams->SetDocURL(newURL.get());
}
return true;
}
void
PrintProgressDialogParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
bool
PrintProgressDialogParent::Recv__delete__()
{
// The child has requested that we tear down the connection, so we set a
// member to make sure we don't try to contact it after the fact.
mActive = false;
return true;
}
// nsIObserver
NS_IMETHODIMP
PrintProgressDialogParent::Observe(nsISupports *aSubject, const char *aTopic,
const char16_t *aData)
{
if (mActive) {
Unused << SendDialogOpened();
} else {
NS_WARNING("The print progress dialog finished opening, but communications "
"with the child have been closed.");
}
return NS_OK;
}
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,64 @@
/* 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 mozilla_embedding_PrintProgressDialogParent_h
#define mozilla_embedding_PrintProgressDialogParent_h
#include "mozilla/embedding/PPrintProgressDialogParent.h"
#include "nsIObserver.h"
class nsIPrintProgressParams;
class nsIWebProgressListener;
namespace mozilla {
namespace embedding {
class PrintProgressDialogParent final : public PPrintProgressDialogParent,
public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
MOZ_IMPLICIT PrintProgressDialogParent();
void SetWebProgressListener(nsIWebProgressListener* aListener);
void SetPrintProgressParams(nsIPrintProgressParams* aParams);
virtual bool
RecvStateChange(
const long& stateFlags,
const nsresult& status) override;
virtual bool
RecvProgressChange(
const long& curSelfProgress,
const long& maxSelfProgress,
const long& curTotalProgress,
const long& maxTotalProgress) override;
virtual bool
RecvDocTitleChange(const nsString& newTitle) override;
virtual bool
RecvDocURLChange(const nsString& newURL) override;
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
virtual bool
Recv__delete__() override;
private:
virtual ~PrintProgressDialogParent();
nsCOMPtr<nsIWebProgressListener> mWebProgressListener;
nsCOMPtr<nsIPrintProgressParams> mPrintProgressParams;
bool mActive;
};
} // namespace embedding
} // namespace mozilla
#endif

View file

@ -0,0 +1,38 @@
/* 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 "PrintSettingsDialogChild.h"
using mozilla::Unused;
namespace mozilla {
namespace embedding {
PrintSettingsDialogChild::PrintSettingsDialogChild()
: mReturned(false)
{
MOZ_COUNT_CTOR(PrintSettingsDialogChild);
}
PrintSettingsDialogChild::~PrintSettingsDialogChild()
{
MOZ_COUNT_DTOR(PrintSettingsDialogChild);
}
bool
PrintSettingsDialogChild::Recv__delete__(const PrintDataOrNSResult& aData)
{
if (aData.type() == PrintDataOrNSResult::Tnsresult) {
mResult = aData.get_nsresult();
MOZ_ASSERT(NS_FAILED(mResult), "expected a failure result");
} else {
mResult = NS_OK;
mData = aData.get_PrintData();
}
mReturned = true;
return true;
}
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,35 @@
/* 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 mozilla_embedding_PrintSettingsDialogChild_h
#define mozilla_embedding_PrintSettingsDialogChild_h
#include "mozilla/embedding/PPrintSettingsDialogChild.h"
namespace mozilla {
namespace embedding {
class PrintSettingsDialogChild final : public PPrintSettingsDialogChild
{
NS_INLINE_DECL_REFCOUNTING(PrintSettingsDialogChild)
public:
MOZ_IMPLICIT PrintSettingsDialogChild();
virtual bool Recv__delete__(const PrintDataOrNSResult& aData) override;
bool returned() { return mReturned; };
nsresult result() { return mResult; };
PrintData data() { return mData; };
private:
virtual ~PrintSettingsDialogChild();
bool mReturned;
nsresult mResult;
PrintData mData;
};
} // namespace embedding
} // namespace mozilla
#endif

View file

@ -0,0 +1,28 @@
/* 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 "PrintSettingsDialogParent.h"
// C++ file contents
namespace mozilla {
namespace embedding {
PrintSettingsDialogParent::PrintSettingsDialogParent()
{
MOZ_COUNT_CTOR(PrintSettingsDialogParent);
}
PrintSettingsDialogParent::~PrintSettingsDialogParent()
{
MOZ_COUNT_DTOR(PrintSettingsDialogParent);
}
void
PrintSettingsDialogParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,29 @@
/* 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 mozilla_embedding_PrintSettingsDialogParent_h
#define mozilla_embedding_PrintSettingsDialogParent_h
#include "mozilla/embedding/PPrintSettingsDialogParent.h"
// Header file contents
namespace mozilla {
namespace embedding {
class PrintSettingsDialogParent final : public PPrintSettingsDialogParent
{
public:
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
MOZ_IMPLICIT PrintSettingsDialogParent();
private:
virtual ~PrintSettingsDialogParent();
};
} // namespace embedding
} // namespace mozilla
#endif

View file

@ -0,0 +1,336 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/dom/Element.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/Preferences.h"
#include "mozilla/Unused.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMWindow.h"
#include "nsIPrintingPromptService.h"
#include "nsIPrintProgressParams.h"
#include "nsIPrintSettingsService.h"
#include "nsIServiceManager.h"
#include "nsServiceManagerUtils.h"
#include "nsIWebProgressListener.h"
#include "PrintingParent.h"
#include "PrintDataUtils.h"
#include "PrintProgressDialogParent.h"
#include "PrintSettingsDialogParent.h"
#include "mozilla/layout/RemotePrintJobParent.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layout;
namespace mozilla {
namespace embedding {
bool
PrintingParent::RecvShowProgress(PBrowserParent* parent,
PPrintProgressDialogParent* printProgressDialog,
PRemotePrintJobParent* remotePrintJob,
const bool& isForPrinting,
bool* notifyOnOpen,
nsresult* result)
{
*result = NS_ERROR_FAILURE;
*notifyOnOpen = false;
nsCOMPtr<nsPIDOMWindowOuter> parentWin = DOMWindowFromBrowserParent(parent);
if (!parentWin) {
return true;
}
nsCOMPtr<nsIPrintingPromptService> pps(do_GetService("@mozilla.org/embedcomp/printingprompt-service;1"));
if (!pps) {
return true;
}
PrintProgressDialogParent* dialogParent =
static_cast<PrintProgressDialogParent*>(printProgressDialog);
nsCOMPtr<nsIObserver> observer = do_QueryInterface(dialogParent);
nsCOMPtr<nsIWebProgressListener> printProgressListener;
nsCOMPtr<nsIPrintProgressParams> printProgressParams;
*result = pps->ShowProgress(parentWin, nullptr, nullptr, observer,
isForPrinting,
getter_AddRefs(printProgressListener),
getter_AddRefs(printProgressParams),
notifyOnOpen);
NS_ENSURE_SUCCESS(*result, true);
if (remotePrintJob) {
// If we have a RemotePrintJob use that as a more general forwarder for
// print progress listeners.
static_cast<RemotePrintJobParent*>(remotePrintJob)
->RegisterListener(printProgressListener);
} else {
dialogParent->SetWebProgressListener(printProgressListener);
}
dialogParent->SetPrintProgressParams(printProgressParams);
return true;
}
nsresult
PrintingParent::ShowPrintDialog(PBrowserParent* aParent,
const PrintData& aData,
PrintData* aResult)
{
// If aParent is null this call is just being used to get print settings from
// the printer for print preview.
bool isPrintPreview = !aParent;
nsCOMPtr<nsPIDOMWindowOuter> parentWin;
if (aParent) {
parentWin = DOMWindowFromBrowserParent(aParent);
if (!parentWin) {
return NS_ERROR_FAILURE;
}
}
nsCOMPtr<nsIPrintingPromptService> pps(do_GetService("@mozilla.org/embedcomp/printingprompt-service;1"));
if (!pps) {
return NS_ERROR_FAILURE;
}
// The initSettings we got can be wrapped using
// PrintDataUtils' MockWebBrowserPrint, which implements enough of
// nsIWebBrowserPrint to keep the dialogs happy.
nsCOMPtr<nsIWebBrowserPrint> wbp = new MockWebBrowserPrint(aData);
// Use the existing RemotePrintJob and its settings, if we have one, to make
// sure they stay current.
RemotePrintJobParent* remotePrintJob =
static_cast<RemotePrintJobParent*>(aData.remotePrintJobParent());
nsCOMPtr<nsIPrintSettings> settings;
nsresult rv;
if (remotePrintJob) {
settings = remotePrintJob->GetPrintSettings();
} else {
rv = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
NS_ENSURE_SUCCESS(rv, rv);
}
// We only want to use the print silently setting from the parent.
bool printSilently;
rv = settings->GetPrintSilent(&printSilently);
NS_ENSURE_SUCCESS(rv, rv);
rv = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings);
NS_ENSURE_SUCCESS(rv, rv);
rv = settings->SetPrintSilent(printSilently);
NS_ENSURE_SUCCESS(rv, rv);
// If this is for print preview or we are printing silently then we just need
// to initialize the print settings with anything specific from the printer.
if (isPrintPreview || printSilently ||
Preferences::GetBool("print.always_print_silent", printSilently)) {
nsXPIDLString printerName;
rv = settings->GetPrinterName(getter_Copies(printerName));
NS_ENSURE_SUCCESS(rv, rv);
settings->SetIsInitializedFromPrinter(false);
mPrintSettingsSvc->InitPrintSettingsFromPrinter(printerName, settings);
} else {
rv = pps->ShowPrintDialog(parentWin, wbp, settings);
NS_ENSURE_SUCCESS(rv, rv);
}
if (isPrintPreview) {
// For print preview we don't want a RemotePrintJob just the settings.
rv = mPrintSettingsSvc->SerializeToPrintData(settings, nullptr, aResult);
} else {
rv = SerializeAndEnsureRemotePrintJob(settings, nullptr, remotePrintJob,
aResult);
}
return rv;
}
bool
PrintingParent::RecvShowPrintDialog(PPrintSettingsDialogParent* aDialog,
PBrowserParent* aParent,
const PrintData& aData)
{
PrintData resultData;
nsresult rv = ShowPrintDialog(aParent, aData, &resultData);
// The child has been spinning an event loop while waiting
// to hear about the print settings. We return the results
// with an async message which frees the child process from
// its nested event loop.
if (NS_FAILED(rv)) {
mozilla::Unused << aDialog->Send__delete__(aDialog, rv);
} else {
mozilla::Unused << aDialog->Send__delete__(aDialog, resultData);
}
return true;
}
bool
PrintingParent::RecvSavePrintSettings(const PrintData& aData,
const bool& aUsePrinterNamePrefix,
const uint32_t& aFlags,
nsresult* aResult)
{
nsCOMPtr<nsIPrintSettings> settings;
*aResult = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
NS_ENSURE_SUCCESS(*aResult, true);
*aResult = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings);
NS_ENSURE_SUCCESS(*aResult, true);
*aResult = mPrintSettingsSvc->SavePrintSettingsToPrefs(settings,
aUsePrinterNamePrefix,
aFlags);
return true;
}
PPrintProgressDialogParent*
PrintingParent::AllocPPrintProgressDialogParent()
{
PrintProgressDialogParent* actor = new PrintProgressDialogParent();
NS_ADDREF(actor); // De-ref'd in the __delete__ handler for
// PrintProgressDialogParent.
return actor;
}
bool
PrintingParent::DeallocPPrintProgressDialogParent(PPrintProgressDialogParent* doomed)
{
// We can't just delete the PrintProgressDialogParent since somebody might
// still be holding a reference to it as nsIObserver, so just decrement the
// refcount instead.
PrintProgressDialogParent* actor = static_cast<PrintProgressDialogParent*>(doomed);
NS_RELEASE(actor);
return true;
}
PPrintSettingsDialogParent*
PrintingParent::AllocPPrintSettingsDialogParent()
{
return new PrintSettingsDialogParent();
}
bool
PrintingParent::DeallocPPrintSettingsDialogParent(PPrintSettingsDialogParent* aDoomed)
{
delete aDoomed;
return true;
}
PRemotePrintJobParent*
PrintingParent::AllocPRemotePrintJobParent()
{
MOZ_ASSERT_UNREACHABLE("No default constructors for implementations.");
return nullptr;
}
bool
PrintingParent::DeallocPRemotePrintJobParent(PRemotePrintJobParent* aDoomed)
{
delete aDoomed;
return true;
}
void
PrintingParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
nsPIDOMWindowOuter*
PrintingParent::DOMWindowFromBrowserParent(PBrowserParent* parent)
{
if (!parent) {
return nullptr;
}
TabParent* tabParent = TabParent::GetFrom(parent);
if (!tabParent) {
return nullptr;
}
nsCOMPtr<Element> frameElement = tabParent->GetOwnerElement();
if (!frameElement) {
return nullptr;
}
nsCOMPtr<nsIContent> frame(do_QueryInterface(frameElement));
if (!frame) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindowOuter> parentWin = frame->OwnerDoc()->GetWindow();
if (!parentWin) {
return nullptr;
}
return parentWin;
}
nsresult
PrintingParent::SerializeAndEnsureRemotePrintJob(
nsIPrintSettings* aPrintSettings, nsIWebProgressListener* aListener,
layout::RemotePrintJobParent* aRemotePrintJob, PrintData* aPrintData)
{
MOZ_ASSERT(aPrintData);
nsresult rv;
nsCOMPtr<nsIPrintSettings> printSettings;
if (aPrintSettings) {
printSettings = aPrintSettings;
} else {
rv = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(printSettings));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
rv = mPrintSettingsSvc->SerializeToPrintData(printSettings, nullptr,
aPrintData);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
RemotePrintJobParent* remotePrintJob;
if (aRemotePrintJob) {
remotePrintJob = aRemotePrintJob;
aPrintData->remotePrintJobParent() = remotePrintJob;
} else {
remotePrintJob = new RemotePrintJobParent(aPrintSettings);
aPrintData->remotePrintJobParent() =
SendPRemotePrintJobConstructor(remotePrintJob);
}
if (aListener) {
remotePrintJob->RegisterListener(aListener);
}
return NS_OK;
}
PrintingParent::PrintingParent()
{
MOZ_COUNT_CTOR(PrintingParent);
mPrintSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1");
MOZ_ASSERT(mPrintSettingsSvc);
}
PrintingParent::~PrintingParent()
{
MOZ_COUNT_DTOR(PrintingParent);
}
} // namespace embedding
} // namespace mozilla

View file

@ -0,0 +1,109 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et 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 mozilla_embedding_PrintingParent_h
#define mozilla_embedding_PrintingParent_h
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/embedding/PPrintingParent.h"
class nsIPrintSettingsService;
class nsIWebProgressListener;
class nsPIDOMWindowOuter;
class PPrintProgressDialogParent;
class PPrintSettingsDialogParent;
namespace mozilla {
namespace layout {
class PRemotePrintJobParent;
class RemotePrintJobParent;
}
namespace embedding {
class PrintingParent final : public PPrintingParent
{
public:
NS_INLINE_DECL_REFCOUNTING(PrintingParent)
virtual bool
RecvShowProgress(PBrowserParent* parent,
PPrintProgressDialogParent* printProgressDialog,
PRemotePrintJobParent* remotePrintJob,
const bool& isForPrinting,
bool* notifyOnOpen,
nsresult* result);
virtual bool
RecvShowPrintDialog(PPrintSettingsDialogParent* aDialog,
PBrowserParent* aParent,
const PrintData& aData);
virtual bool
RecvSavePrintSettings(const PrintData& data,
const bool& usePrinterNamePrefix,
const uint32_t& flags,
nsresult* rv);
virtual PPrintProgressDialogParent*
AllocPPrintProgressDialogParent();
virtual bool
DeallocPPrintProgressDialogParent(PPrintProgressDialogParent* aActor);
virtual PPrintSettingsDialogParent*
AllocPPrintSettingsDialogParent();
virtual bool
DeallocPPrintSettingsDialogParent(PPrintSettingsDialogParent* aActor);
virtual PRemotePrintJobParent*
AllocPRemotePrintJobParent();
virtual bool
DeallocPRemotePrintJobParent(PRemotePrintJobParent* aActor);
virtual void
ActorDestroy(ActorDestroyReason aWhy);
MOZ_IMPLICIT PrintingParent();
/**
* Serialize nsIPrintSettings to PrintData ready for sending to a child
* process. A RemotePrintJob will be created and added to the PrintData.
* An optional progress listener can be given, which will be registered
* with the RemotePrintJob, so that progress can be tracked in the parent.
*
* @param aPrintSettings optional print settings to serialize, otherwise a
* default print settings will be used.
* @param aProgressListener optional print progress listener.
* @param aRemotePrintJob optional remote print job, so that an existing
* one can be used.
* @param aPrintData PrintData to populate.
*/
nsresult
SerializeAndEnsureRemotePrintJob(nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aListener,
layout::RemotePrintJobParent* aRemotePrintJob,
PrintData* aPrintData);
private:
virtual ~PrintingParent();
nsPIDOMWindowOuter*
DOMWindowFromBrowserParent(PBrowserParent* parent);
nsresult
ShowPrintDialog(PBrowserParent* parent,
const PrintData& data,
PrintData* result);
nsCOMPtr<nsIPrintSettingsService> mPrintSettingsSvc;
};
} // namespace embedding
} // namespace mozilla
#endif

View file

@ -0,0 +1,35 @@
# -*- 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/.
EXPORTS += [
'nsPrintingProxy.h',
]
EXPORTS.mozilla.embedding.printingui += [
'PrintingParent.h',
]
if CONFIG['NS_PRINTING']:
UNIFIED_SOURCES += [
'nsPrintingProxy.cpp',
'PrintDataUtils.cpp',
'PrintingParent.cpp',
'PrintProgressDialogChild.cpp',
'PrintProgressDialogParent.cpp',
'PrintSettingsDialogChild.cpp',
'PrintSettingsDialogParent.cpp',
]
IPDL_SOURCES += [
'PPrinting.ipdl',
'PPrintingTypes.ipdlh',
'PPrintProgressDialog.ipdl',
'PPrintSettingsDialog.ipdl',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

View file

@ -0,0 +1,269 @@
/* -*- 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 "nsPrintingProxy.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/layout/RemotePrintJobChild.h"
#include "mozilla/Unused.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIPrintingPromptService.h"
#include "nsIPrintSession.h"
#include "nsPIDOMWindow.h"
#include "nsPrintOptionsImpl.h"
#include "nsServiceManagerUtils.h"
#include "PrintDataUtils.h"
#include "PrintProgressDialogChild.h"
#include "PrintSettingsDialogChild.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::embedding;
using namespace mozilla::layout;
static StaticRefPtr<nsPrintingProxy> sPrintingProxyInstance;
NS_IMPL_ISUPPORTS(nsPrintingProxy, nsIPrintingPromptService)
nsPrintingProxy::nsPrintingProxy()
{
}
nsPrintingProxy::~nsPrintingProxy()
{
}
/* static */
already_AddRefed<nsPrintingProxy>
nsPrintingProxy::GetInstance()
{
if (!sPrintingProxyInstance) {
sPrintingProxyInstance = new nsPrintingProxy();
if (!sPrintingProxyInstance) {
return nullptr;
}
nsresult rv = sPrintingProxyInstance->Init();
if (NS_FAILED(rv)) {
sPrintingProxyInstance = nullptr;
return nullptr;
}
ClearOnShutdown(&sPrintingProxyInstance);
}
RefPtr<nsPrintingProxy> inst = sPrintingProxyInstance.get();
return inst.forget();
}
nsresult
nsPrintingProxy::Init()
{
mozilla::Unused << ContentChild::GetSingleton()->SendPPrintingConstructor(this);
return NS_OK;
}
NS_IMETHODIMP
nsPrintingProxy::ShowPrintDialog(mozIDOMWindowProxy *parent,
nsIWebBrowserPrint *webBrowserPrint,
nsIPrintSettings *printSettings)
{
NS_ENSURE_ARG(webBrowserPrint);
NS_ENSURE_ARG(printSettings);
// If parent is null we are just being called to retrieve the print settings
// from the printer in the parent for print preview.
TabChild* pBrowser = nullptr;
if (parent) {
// Get the TabChild for this nsIDOMWindow, which we can then pass up to
// the parent.
nsCOMPtr<nsPIDOMWindowOuter> pwin = nsPIDOMWindowOuter::From(parent);
NS_ENSURE_STATE(pwin);
nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
NS_ENSURE_STATE(docShell);
nsCOMPtr<nsITabChild> tabchild = docShell->GetTabChild();
NS_ENSURE_STATE(tabchild);
pBrowser = static_cast<TabChild*>(tabchild.get());
}
// Next, serialize the nsIWebBrowserPrint and nsIPrintSettings we were given.
nsresult rv = NS_OK;
nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PrintData inSettings;
rv = printSettingsSvc->SerializeToPrintData(printSettings, webBrowserPrint,
&inSettings);
NS_ENSURE_SUCCESS(rv, rv);
// Now, the waiting game. The parent process should be showing
// the printing dialog soon. In the meantime, we need to spin a
// nested event loop while we wait for the results of the dialog
// to be returned to us.
RefPtr<PrintSettingsDialogChild> dialog = new PrintSettingsDialogChild();
SendPPrintSettingsDialogConstructor(dialog);
mozilla::Unused << SendShowPrintDialog(dialog, pBrowser, inSettings);
while(!dialog->returned()) {
NS_ProcessNextEvent(nullptr, true);
}
rv = dialog->result();
NS_ENSURE_SUCCESS(rv, rv);
rv = printSettingsSvc->DeserializeToPrintSettings(dialog->data(),
printSettings);
return NS_OK;
}
NS_IMETHODIMP
nsPrintingProxy::ShowProgress(mozIDOMWindowProxy* parent,
nsIWebBrowserPrint* webBrowserPrint, // ok to be null
nsIPrintSettings* printSettings, // ok to be null
nsIObserver* openDialogObserver, // ok to be null
bool isForPrinting,
nsIWebProgressListener** webProgressListener,
nsIPrintProgressParams** printProgressParams,
bool* notifyOnOpen)
{
NS_ENSURE_ARG(parent);
NS_ENSURE_ARG(webProgressListener);
NS_ENSURE_ARG(printProgressParams);
NS_ENSURE_ARG(notifyOnOpen);
// Get the TabChild for this nsIDOMWindow, which we can then pass up to
// the parent.
nsCOMPtr<nsPIDOMWindowOuter> pwin = nsPIDOMWindowOuter::From(parent);
NS_ENSURE_STATE(pwin);
nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell();
NS_ENSURE_STATE(docShell);
nsCOMPtr<nsITabChild> tabchild = docShell->GetTabChild();
TabChild* pBrowser = static_cast<TabChild*>(tabchild.get());
RefPtr<PrintProgressDialogChild> dialogChild =
new PrintProgressDialogChild(openDialogObserver);
SendPPrintProgressDialogConstructor(dialogChild);
// Get the RemotePrintJob if we have one available.
RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
if (printSettings) {
nsCOMPtr<nsIPrintSession> printSession;
nsresult rv = printSettings->GetPrintSession(getter_AddRefs(printSession));
if (NS_SUCCEEDED(rv) && printSession) {
printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
}
}
nsresult rv = NS_OK;
mozilla::Unused << SendShowProgress(pBrowser, dialogChild, remotePrintJob,
isForPrinting, notifyOnOpen, &rv);
if (NS_FAILED(rv)) {
return rv;
}
// If we have a RemotePrintJob that will be being used as a more general
// forwarder for print progress listeners. Once we always have one we can
// remove the interface from PrintProgressDialogChild.
if (!remotePrintJob) {
NS_ADDREF(*webProgressListener = dialogChild);
}
NS_ADDREF(*printProgressParams = dialogChild);
return NS_OK;
}
NS_IMETHODIMP
nsPrintingProxy::ShowPageSetup(mozIDOMWindowProxy *parent,
nsIPrintSettings *printSettings,
nsIObserver *aObs)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsPrintingProxy::ShowPrinterProperties(mozIDOMWindowProxy *parent,
const char16_t *printerName,
nsIPrintSettings *printSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsPrintingProxy::SavePrintSettings(nsIPrintSettings* aPS,
bool aUsePrinterNamePrefix,
uint32_t aFlags)
{
nsresult rv;
nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PrintData settings;
rv = printSettingsSvc->SerializeToPrintData(aPS, nullptr, &settings);
NS_ENSURE_SUCCESS(rv, rv);
Unused << SendSavePrintSettings(settings, aUsePrinterNamePrefix, aFlags,
&rv);
return rv;
}
PPrintProgressDialogChild*
nsPrintingProxy::AllocPPrintProgressDialogChild()
{
// The parent process will never initiate the PPrintProgressDialog
// protocol connection, so no need to provide an allocator here.
NS_NOTREACHED("Allocator for PPrintProgressDialogChild should not be "
"called on nsPrintingProxy.");
return nullptr;
}
bool
nsPrintingProxy::DeallocPPrintProgressDialogChild(PPrintProgressDialogChild* aActor)
{
// The PrintProgressDialogChild implements refcounting, and
// will take itself out.
return true;
}
PPrintSettingsDialogChild*
nsPrintingProxy::AllocPPrintSettingsDialogChild()
{
// The parent process will never initiate the PPrintSettingsDialog
// protocol connection, so no need to provide an allocator here.
NS_NOTREACHED("Allocator for PPrintSettingsDialogChild should not be "
"called on nsPrintingProxy.");
return nullptr;
}
bool
nsPrintingProxy::DeallocPPrintSettingsDialogChild(PPrintSettingsDialogChild* aActor)
{
// The PrintSettingsDialogChild implements refcounting, and
// will take itself out.
return true;
}
PRemotePrintJobChild*
nsPrintingProxy::AllocPRemotePrintJobChild()
{
RefPtr<RemotePrintJobChild> remotePrintJob = new RemotePrintJobChild();
return remotePrintJob.forget().take();
}
bool
nsPrintingProxy::DeallocPRemotePrintJobChild(PRemotePrintJobChild* aDoomed)
{
RemotePrintJobChild* remotePrintJob = static_cast<RemotePrintJobChild*>(aDoomed);
NS_RELEASE(remotePrintJob);
return true;
}

View file

@ -0,0 +1,57 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintingProxy_h
#define __nsPrintingProxy_h
#include "nsIPrintingPromptService.h"
#include "mozilla/embedding/PPrintingChild.h"
namespace mozilla {
namespace layout {
class PRemotePrintJobChild;
}
}
class nsPrintingProxy: public nsIPrintingPromptService,
public mozilla::embedding::PPrintingChild
{
virtual ~nsPrintingProxy();
public:
nsPrintingProxy();
static already_AddRefed<nsPrintingProxy> GetInstance();
nsresult Init();
NS_DECL_ISUPPORTS
NS_DECL_NSIPRINTINGPROMPTSERVICE
nsresult SavePrintSettings(nsIPrintSettings* aPS,
bool aUsePrinterNamePrefix,
uint32_t aFlags);
virtual PPrintProgressDialogChild*
AllocPPrintProgressDialogChild() override;
virtual bool
DeallocPPrintProgressDialogChild(PPrintProgressDialogChild* aActor) override;
virtual PPrintSettingsDialogChild*
AllocPPrintSettingsDialogChild() override;
virtual bool
DeallocPPrintSettingsDialogChild(PPrintSettingsDialogChild* aActor) override;
virtual PRemotePrintJobChild*
AllocPRemotePrintJobChild() override;
virtual bool
DeallocPRemotePrintJobChild(PRemotePrintJobChild* aActor) override;
};
#endif

View file

@ -0,0 +1,16 @@
# -*- 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/.
UNIFIED_SOURCES += [
'nsPrintProgress.cpp',
'nsPrintProgressParams.cpp',
]
SOURCES += [
'nsPrintingPromptServiceX.mm',
]
FINAL_LIBRARY = 'xul'

View file

@ -0,0 +1,213 @@
/* -*- Mode: C++; 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 "nsPrintProgress.h"
#include "nsIBaseWindow.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIComponentManager.h"
#include "nsPIDOMWindow.h"
NS_IMPL_ADDREF(nsPrintProgress)
NS_IMPL_RELEASE(nsPrintProgress)
NS_INTERFACE_MAP_BEGIN(nsPrintProgress)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrintStatusFeedback)
NS_INTERFACE_MAP_ENTRY(nsIPrintProgress)
NS_INTERFACE_MAP_ENTRY(nsIPrintStatusFeedback)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_END_THREADSAFE
nsPrintProgress::nsPrintProgress()
{
m_closeProgress = false;
m_processCanceled = false;
m_pendingStateFlags = -1;
m_pendingStateValue = NS_OK;
}
nsPrintProgress::~nsPrintProgress()
{
(void)ReleaseListeners();
}
NS_IMETHODIMP nsPrintProgress::OpenProgressDialog(mozIDOMWindowProxy *parent,
const char *dialogURL,
nsISupports *parameters,
nsIObserver *openDialogObserver,
bool *notifyOnOpen)
{
MOZ_ASSERT_UNREACHABLE("The nsPrintingPromptService::ShowProgress "
"implementation for OS X returns "
"NS_ERROR_NOT_IMPLEMENTED, so we should never get "
"here.");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::CloseProgressDialog(bool forceClose)
{
MOZ_ASSERT_UNREACHABLE("The nsPrintingPromptService::ShowProgress "
"implementation for OS X returns "
"NS_ERROR_NOT_IMPLEMENTED, so we should never get "
"here.");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::GetPrompter(nsIPrompt **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = nullptr;
if (! m_closeProgress && m_dialog) {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(m_dialog);
MOZ_ASSERT(window);
return window->GetPrompter(_retval);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsPrintProgress::GetProcessCanceledByUser(bool *aProcessCanceledByUser)
{
NS_ENSURE_ARG_POINTER(aProcessCanceledByUser);
*aProcessCanceledByUser = m_processCanceled;
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::SetProcessCanceledByUser(bool aProcessCanceledByUser)
{
m_processCanceled = aProcessCanceledByUser;
OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::RegisterListener(nsIWebProgressListener * listener)
{
if (!listener) //Nothing to do with a null listener!
return NS_OK;
m_listenerList.AppendObject(listener);
if (m_closeProgress || m_processCanceled)
listener->OnStateChange(nullptr, nullptr,
nsIWebProgressListener::STATE_STOP, NS_OK);
else
{
listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
if (m_pendingStateFlags != -1)
listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::UnregisterListener(nsIWebProgressListener *listener)
{
if (listener)
m_listenerList.RemoveObject(listener);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::DoneIniting()
{
if (m_observer) {
m_observer->Observe(nullptr, nullptr, nullptr);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
{
m_pendingStateFlags = aStateFlags;
m_pendingStateValue = aStatus;
uint32_t count = m_listenerList.Count();
for (uint32_t i = count - 1; i < count; i --)
{
nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
if (progressListener)
progressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
{
uint32_t count = m_listenerList.Count();
for (uint32_t i = count - 1; i < count; i --)
{
nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
if (progressListener)
progressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
{
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const char16_t *aMessage)
{
if (aMessage && *aMessage)
m_pendingStatus = aMessage;
uint32_t count = m_listenerList.Count();
for (uint32_t i = count - 1; i < count; i --)
{
nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
if (progressListener)
progressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
{
return NS_OK;
}
nsresult nsPrintProgress::ReleaseListeners()
{
m_listenerList.Clear();
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::ShowStatusString(const char16_t *status)
{
return OnStatusChange(nullptr, nullptr, NS_OK, status);
}
NS_IMETHODIMP nsPrintProgress::StartMeteors()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::StopMeteors()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::ShowProgress(int32_t percent)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::SetDocShell(nsIDocShell *shell,
mozIDOMWindowProxy *window)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::CloseWindow()
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View file

@ -0,0 +1,44 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintProgress_h
#define __nsPrintProgress_h
#include "nsIPrintProgress.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsIPrintStatusFeedback.h"
#include "nsIObserver.h"
#include "nsString.h"
class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIPRINTPROGRESS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSIPRINTSTATUSFEEDBACK
nsPrintProgress();
protected:
virtual ~nsPrintProgress();
private:
nsresult ReleaseListeners();
bool m_closeProgress;
bool m_processCanceled;
nsString m_pendingStatus;
int32_t m_pendingStateFlags;
nsresult m_pendingStateValue;
// XXX This member is read-only.
nsCOMPtr<mozIDOMWindowProxy> m_dialog;
nsCOMArray<nsIWebProgressListener> m_listenerList;
nsCOMPtr<nsIObserver> m_observer;
};
#endif

View file

@ -0,0 +1,47 @@
/* -*- Mode: C++; 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 "nsPrintProgressParams.h"
#include "nsReadableUtils.h"
NS_IMPL_ISUPPORTS(nsPrintProgressParams, nsIPrintProgressParams)
nsPrintProgressParams::nsPrintProgressParams()
{
}
nsPrintProgressParams::~nsPrintProgressParams()
{
}
NS_IMETHODIMP nsPrintProgressParams::GetDocTitle(char16_t * *aDocTitle)
{
NS_ENSURE_ARG(aDocTitle);
*aDocTitle = ToNewUnicode(mDocTitle);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgressParams::SetDocTitle(const char16_t * aDocTitle)
{
mDocTitle = aDocTitle;
return NS_OK;
}
NS_IMETHODIMP nsPrintProgressParams::GetDocURL(char16_t * *aDocURL)
{
NS_ENSURE_ARG(aDocURL);
*aDocURL = ToNewUnicode(mDocURL);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgressParams::SetDocURL(const char16_t * aDocURL)
{
mDocURL = aDocURL;
return NS_OK;
}

View file

@ -0,0 +1,28 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintProgressParams_h
#define __nsPrintProgressParams_h
#include "nsIPrintProgressParams.h"
#include "nsString.h"
class nsPrintProgressParams : public nsIPrintProgressParams
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPRINTPROGRESSPARAMS
nsPrintProgressParams();
protected:
virtual ~nsPrintProgressParams();
private:
nsString mDocTitle;
nsString mDocURL;
};
#endif

View file

@ -0,0 +1,43 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintingPromptService_h
#define __nsPrintingPromptService_h
// {E042570C-62DE-4bb6-A6E0-798E3C07B4DF}
#define NS_PRINTINGPROMPTSERVICE_CID \
{0xe042570c, 0x62de, 0x4bb6, { 0xa6, 0xe0, 0x79, 0x8e, 0x3c, 0x7, 0xb4, 0xdf}}
#define NS_PRINTINGPROMPTSERVICE_CONTRACTID \
"@mozilla.org/embedcomp/printingprompt-service;1"
#include "nsCOMPtr.h"
#include "nsIPrintingPromptService.h"
#include "nsPIPromptService.h"
#include "nsIWindowWatcher.h"
// Printing Progress Includes
#include "nsPrintProgress.h"
#include "nsIWebProgressListener.h"
class nsPrintingPromptService: public nsIPrintingPromptService,
public nsIWebProgressListener
{
public:
nsPrintingPromptService();
nsresult Init();
NS_DECL_NSIPRINTINGPROMPTSERVICE
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_ISUPPORTS
protected:
virtual ~nsPrintingPromptService();
private:
nsCOMPtr<nsIPrintProgress> mPrintProgress;
};
#endif

View file

@ -0,0 +1,128 @@
/* -*- 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 "nsPrintingPromptService.h"
#include "nsCOMPtr.h"
#include "nsServiceManagerUtils.h"
#include "nsObjCExceptions.h"
#include "nsIPrintingPromptService.h"
#include "nsIFactory.h"
#include "nsIPrintDialogService.h"
#include "nsPIDOMWindow.h"
//*****************************************************************************
// nsPrintingPromptService
//*****************************************************************************
NS_IMPL_ISUPPORTS(nsPrintingPromptService, nsIPrintingPromptService, nsIWebProgressListener)
nsPrintingPromptService::nsPrintingPromptService()
{
}
nsPrintingPromptService::~nsPrintingPromptService()
{
}
nsresult nsPrintingPromptService::Init()
{
return NS_OK;
}
//*****************************************************************************
// nsPrintingPromptService::nsIPrintingPromptService
//*****************************************************************************
NS_IMETHODIMP
nsPrintingPromptService::ShowPrintDialog(mozIDOMWindowProxy *parent, nsIWebBrowserPrint *webBrowserPrint, nsIPrintSettings *printSettings)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
nsCOMPtr<nsIPrintDialogService> dlgPrint(do_GetService(
NS_PRINTDIALOGSERVICE_CONTRACTID));
if (dlgPrint) {
return dlgPrint->Show(nsPIDOMWindowOuter::From(parent), printSettings,
webBrowserPrint);
}
return NS_ERROR_FAILURE;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowProgress(mozIDOMWindowProxy* parent,
nsIWebBrowserPrint* webBrowserPrint, // ok to be null
nsIPrintSettings* printSettings, // ok to be null
nsIObserver* openDialogObserver, // ok to be null
bool isForPrinting,
nsIWebProgressListener** webProgressListener,
nsIPrintProgressParams** printProgressParams,
bool* notifyOnOpen)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPageSetup(mozIDOMWindowProxy *parent, nsIPrintSettings *printSettings, nsIObserver *aObs)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
nsCOMPtr<nsIPrintDialogService> dlgPrint(do_GetService(
NS_PRINTDIALOGSERVICE_CONTRACTID));
if (dlgPrint) {
return dlgPrint->ShowPageSetup(nsPIDOMWindowOuter::From(parent), printSettings);
}
return NS_ERROR_FAILURE;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPrinterProperties(mozIDOMWindowProxy *parent, const char16_t *printerName, nsIPrintSettings *printSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//*****************************************************************************
// nsPrintingPromptService::nsIWebProgressListener
//*****************************************************************************
NS_IMETHODIMP
nsPrintingPromptService::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
{
return NS_OK;
}
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
NS_IMETHODIMP
nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
{
return NS_OK;
}
/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
NS_IMETHODIMP
nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
{
return NS_OK;
}
/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
NS_IMETHODIMP
nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const char16_t *aMessage)
{
return NS_OK;
}
/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
NS_IMETHODIMP
nsPrintingPromptService::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
{
return NS_OK;
}

View file

@ -0,0 +1,17 @@
# -*- 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/.
toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
DIRS += ['ipc']
if CONFIG['NS_PRINTING']:
if toolkit == 'windows':
DIRS += ['win']
elif toolkit == 'cocoa':
DIRS += ['mac']
elif CONFIG['MOZ_PDF_PRINTING']:
DIRS += ['unixshared']

View file

@ -0,0 +1,13 @@
# -*- 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/.
UNIFIED_SOURCES += [
'nsPrintingPromptService.cpp',
'nsPrintProgress.cpp',
'nsPrintProgressParams.cpp',
]
FINAL_LIBRARY = 'xul'

View file

@ -0,0 +1,267 @@
/* -*- Mode: C++; 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 "nsPrintProgress.h"
#include "nsArray.h"
#include "nsIBaseWindow.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIXULWindow.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIComponentManager.h"
#include "nsPIDOMWindow.h"
NS_IMPL_ADDREF(nsPrintProgress)
NS_IMPL_RELEASE(nsPrintProgress)
NS_INTERFACE_MAP_BEGIN(nsPrintProgress)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrintStatusFeedback)
NS_INTERFACE_MAP_ENTRY(nsIPrintProgress)
NS_INTERFACE_MAP_ENTRY(nsIPrintStatusFeedback)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_END_THREADSAFE
nsPrintProgress::nsPrintProgress(nsIPrintSettings* aPrintSettings)
{
m_closeProgress = false;
m_processCanceled = false;
m_pendingStateFlags = -1;
m_pendingStateValue = NS_OK;
m_PrintSetting = aPrintSettings;
}
nsPrintProgress::~nsPrintProgress()
{
(void)ReleaseListeners();
}
NS_IMETHODIMP nsPrintProgress::OpenProgressDialog(mozIDOMWindowProxy *parent,
const char *dialogURL,
nsISupports *parameters,
nsIObserver *openDialogObserver,
bool *notifyOnOpen)
{
*notifyOnOpen = true;
m_observer = openDialogObserver;
nsresult rv = NS_ERROR_FAILURE;
if (m_dialog)
return NS_ERROR_ALREADY_INITIALIZED;
if (!dialogURL || !*dialogURL)
return NS_ERROR_INVALID_ARG;
if (parent)
{
// Set up window.arguments[0]...
nsCOMPtr<nsIMutableArray> array = nsArray::Create();
nsCOMPtr<nsISupportsInterfacePointer> ifptr =
do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
ifptr->SetData(static_cast<nsIPrintProgress*>(this));
ifptr->SetDataIID(&NS_GET_IID(nsIPrintProgress));
array->AppendElement(ifptr, /*weak =*/ false);
array->AppendElement(parameters, /*weak =*/ false);
// We will set the opener of the dialog to be the nsIDOMWindow for the
// browser XUL window itself, as opposed to the content. That way, the
// progress window has access to the opener.
auto* pParentWindow = nsPIDOMWindowOuter::From(parent);
nsCOMPtr<nsIDocShell> docShell = pParentWindow->GetDocShell();
NS_ENSURE_STATE(docShell);
nsCOMPtr<nsIDocShellTreeOwner> owner;
docShell->GetTreeOwner(getter_AddRefs(owner));
nsCOMPtr<nsIXULWindow> ownerXULWindow = do_GetInterface(owner);
nsCOMPtr<mozIDOMWindowProxy> ownerWindow = do_GetInterface(ownerXULWindow);
NS_ENSURE_STATE(ownerWindow);
nsCOMPtr<nsPIDOMWindowOuter> piOwnerWindow = nsPIDOMWindowOuter::From(ownerWindow);
// Open the dialog.
nsCOMPtr<nsPIDOMWindowOuter> newWindow;
rv = piOwnerWindow->OpenDialog(NS_ConvertASCIItoUTF16(dialogURL),
NS_LITERAL_STRING("_blank"),
NS_LITERAL_STRING("chrome,titlebar,dependent,centerscreen"),
array, getter_AddRefs(newWindow));
}
return rv;
}
NS_IMETHODIMP nsPrintProgress::CloseProgressDialog(bool forceClose)
{
m_closeProgress = true;
// XXX Invalid cast of bool to nsresult (bug 778106)
return OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP,
(nsresult)forceClose);
}
NS_IMETHODIMP nsPrintProgress::GetPrompter(nsIPrompt **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = nullptr;
if (! m_closeProgress && m_dialog) {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(m_dialog);
MOZ_ASSERT(window);
return window->GetPrompter(_retval);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsPrintProgress::GetProcessCanceledByUser(bool *aProcessCanceledByUser)
{
NS_ENSURE_ARG_POINTER(aProcessCanceledByUser);
*aProcessCanceledByUser = m_processCanceled;
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::SetProcessCanceledByUser(bool aProcessCanceledByUser)
{
if(m_PrintSetting)
m_PrintSetting->SetIsCancelled(true);
m_processCanceled = aProcessCanceledByUser;
OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::RegisterListener(nsIWebProgressListener * listener)
{
if (!listener) //Nothing to do with a null listener!
return NS_OK;
m_listenerList.AppendObject(listener);
if (m_closeProgress || m_processCanceled)
listener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
else
{
listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
if (m_pendingStateFlags != -1)
listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::UnregisterListener(nsIWebProgressListener *listener)
{
if (listener)
m_listenerList.RemoveObject(listener);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::DoneIniting()
{
if (m_observer) {
m_observer->Observe(nullptr, nullptr, nullptr);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
{
m_pendingStateFlags = aStateFlags;
m_pendingStateValue = aStatus;
uint32_t count = m_listenerList.Count();
for (uint32_t i = count - 1; i < count; i --)
{
nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
if (progressListener)
progressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
{
uint32_t count = m_listenerList.Count();
for (uint32_t i = count - 1; i < count; i --)
{
nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
if (progressListener)
progressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const char16_t *aMessage)
{
if (aMessage && *aMessage)
m_pendingStatus = aMessage;
uint32_t count = m_listenerList.Count();
for (uint32_t i = count - 1; i < count; i --)
{
nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
if (progressListener)
progressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
{
return NS_OK;
}
nsresult nsPrintProgress::ReleaseListeners()
{
m_listenerList.Clear();
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::ShowStatusString(const char16_t *status)
{
return OnStatusChange(nullptr, nullptr, NS_OK, status);
}
NS_IMETHODIMP nsPrintProgress::StartMeteors()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::StopMeteors()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::ShowProgress(int32_t percent)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::SetDocShell(nsIDocShell *shell, mozIDOMWindowProxy *window)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::CloseWindow()
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View file

@ -0,0 +1,46 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintProgress_h
#define __nsPrintProgress_h
#include "nsIPrintProgress.h"
#include "nsIPrintingPromptService.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsIDOMWindow.h"
#include "nsIPrintStatusFeedback.h"
#include "nsIObserver.h"
#include "nsString.h"
class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIPRINTPROGRESS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSIPRINTSTATUSFEEDBACK
explicit nsPrintProgress(nsIPrintSettings* aPrintSettings);
protected:
virtual ~nsPrintProgress();
private:
nsresult ReleaseListeners();
bool m_closeProgress;
bool m_processCanceled;
nsString m_pendingStatus;
int32_t m_pendingStateFlags;
nsresult m_pendingStateValue;
nsCOMPtr<nsIDOMWindow> m_dialog;
nsCOMArray<nsIWebProgressListener> m_listenerList;
nsCOMPtr<nsIObserver> m_observer;
nsCOMPtr<nsIPrintSettings> m_PrintSetting;
};
#endif

View file

@ -0,0 +1,47 @@
/* -*- Mode: C++; 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 "nsPrintProgressParams.h"
#include "nsReadableUtils.h"
NS_IMPL_ISUPPORTS(nsPrintProgressParams, nsIPrintProgressParams)
nsPrintProgressParams::nsPrintProgressParams()
{
}
nsPrintProgressParams::~nsPrintProgressParams()
{
}
NS_IMETHODIMP nsPrintProgressParams::GetDocTitle(char16_t * *aDocTitle)
{
NS_ENSURE_ARG(aDocTitle);
*aDocTitle = ToNewUnicode(mDocTitle);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgressParams::SetDocTitle(const char16_t * aDocTitle)
{
mDocTitle = aDocTitle;
return NS_OK;
}
NS_IMETHODIMP nsPrintProgressParams::GetDocURL(char16_t * *aDocURL)
{
NS_ENSURE_ARG(aDocURL);
*aDocURL = ToNewUnicode(mDocURL);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgressParams::SetDocURL(const char16_t * aDocURL)
{
mDocURL = aDocURL;
return NS_OK;
}

View file

@ -0,0 +1,28 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintProgressParams_h
#define __nsPrintProgressParams_h
#include "nsIPrintProgressParams.h"
#include "nsString.h"
class nsPrintProgressParams : public nsIPrintProgressParams
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPRINTPROGRESSPARAMS
nsPrintProgressParams();
protected:
virtual ~nsPrintProgressParams();
private:
nsString mDocTitle;
nsString mDocURL;
};
#endif

View file

@ -0,0 +1,298 @@
/* -*- 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 "nsPrintingPromptService.h"
#include "nsArray.h"
#include "nsIComponentManager.h"
#include "nsIDialogParamBlock.h"
#include "nsIDOMWindow.h"
#include "nsIServiceManager.h"
#include "nsISupportsUtils.h"
#include "nsString.h"
#include "nsIPrintDialogService.h"
// Printing Progress Includes
#include "nsPrintProgress.h"
#include "nsPrintProgressParams.h"
static const char *kPrintDialogURL = "chrome://global/content/printdialog.xul";
static const char *kPrintProgressDialogURL = "chrome://global/content/printProgress.xul";
static const char *kPrtPrvProgressDialogURL = "chrome://global/content/printPreviewProgress.xul";
static const char *kPageSetupDialogURL = "chrome://global/content/printPageSetup.xul";
static const char *kPrinterPropertiesURL = "chrome://global/content/printjoboptions.xul";
/****************************************************************
************************* ParamBlock ***************************
****************************************************************/
class ParamBlock {
public:
ParamBlock()
{
mBlock = 0;
}
~ParamBlock()
{
NS_IF_RELEASE(mBlock);
}
nsresult Init() {
return CallCreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &mBlock);
}
nsIDialogParamBlock * operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { return mBlock; }
operator nsIDialogParamBlock * () const { return mBlock; }
private:
nsIDialogParamBlock *mBlock;
};
/****************************************************************
***************** nsPrintingPromptService **********************
****************************************************************/
NS_IMPL_ISUPPORTS(nsPrintingPromptService, nsIPrintingPromptService, nsIWebProgressListener)
nsPrintingPromptService::nsPrintingPromptService()
{
}
nsPrintingPromptService::~nsPrintingPromptService()
{
}
nsresult
nsPrintingPromptService::Init()
{
nsresult rv;
mWatcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
return rv;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPrintDialog(mozIDOMWindowProxy *parent,
nsIWebBrowserPrint *webBrowserPrint,
nsIPrintSettings *printSettings)
{
NS_ENSURE_ARG(webBrowserPrint);
NS_ENSURE_ARG(printSettings);
// Try to access a component dialog
nsCOMPtr<nsIPrintDialogService> dlgPrint(do_GetService(
NS_PRINTDIALOGSERVICE_CONTRACTID));
if (dlgPrint)
return dlgPrint->Show(nsPIDOMWindowOuter::From(parent),
printSettings, webBrowserPrint);
// Show the built-in dialog instead
ParamBlock block;
nsresult rv = block.Init();
if (NS_FAILED(rv))
return rv;
block->SetInt(0, 0);
return DoDialog(parent, block, webBrowserPrint, printSettings, kPrintDialogURL);
}
NS_IMETHODIMP
nsPrintingPromptService::ShowProgress(mozIDOMWindowProxy* parent,
nsIWebBrowserPrint* webBrowserPrint, // ok to be null
nsIPrintSettings* printSettings, // ok to be null
nsIObserver* openDialogObserver, // ok to be null
bool isForPrinting,
nsIWebProgressListener** webProgressListener,
nsIPrintProgressParams** printProgressParams,
bool* notifyOnOpen)
{
NS_ENSURE_ARG(webProgressListener);
NS_ENSURE_ARG(printProgressParams);
NS_ENSURE_ARG(notifyOnOpen);
*notifyOnOpen = false;
nsPrintProgress* prtProgress = new nsPrintProgress(printSettings);
mPrintProgress = prtProgress;
mWebProgressListener = prtProgress;
nsCOMPtr<nsIPrintProgressParams> prtProgressParams = new nsPrintProgressParams();
nsCOMPtr<mozIDOMWindowProxy> parentWindow = parent;
if (mWatcher && !parentWindow) {
mWatcher->GetActiveWindow(getter_AddRefs(parentWindow));
}
if (parentWindow) {
mPrintProgress->OpenProgressDialog(parentWindow,
isForPrinting ? kPrintProgressDialogURL : kPrtPrvProgressDialogURL,
prtProgressParams, openDialogObserver, notifyOnOpen);
}
prtProgressParams.forget(printProgressParams);
NS_ADDREF(*webProgressListener = this);
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPageSetup(mozIDOMWindowProxy *parent,
nsIPrintSettings *printSettings,
nsIObserver *aObs)
{
NS_ENSURE_ARG(printSettings);
// Try to access a component dialog
nsCOMPtr<nsIPrintDialogService> dlgPrint(do_GetService(
NS_PRINTDIALOGSERVICE_CONTRACTID));
if (dlgPrint)
return dlgPrint->ShowPageSetup(nsPIDOMWindowOuter::From(parent),
printSettings);
ParamBlock block;
nsresult rv = block.Init();
if (NS_FAILED(rv))
return rv;
block->SetInt(0, 0);
return DoDialog(parent, block, nullptr, printSettings, kPageSetupDialogURL);
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPrinterProperties(mozIDOMWindowProxy *parent,
const char16_t *printerName,
nsIPrintSettings *printSettings)
{
/* fixme: We simply ignore the |aPrinter| argument here
* We should get the supported printer attributes from the printer and
* populate the print job options dialog with these data instead of using
* the "default set" here.
* However, this requires changes on all platforms and is another big chunk
* of patches ... ;-(
*/
NS_ENSURE_ARG(printerName);
NS_ENSURE_ARG(printSettings);
ParamBlock block;
nsresult rv = block.Init();
if (NS_FAILED(rv))
return rv;
block->SetInt(0, 0);
return DoDialog(parent, block, nullptr, printSettings, kPrinterPropertiesURL);
}
nsresult
nsPrintingPromptService::DoDialog(mozIDOMWindowProxy *aParent,
nsIDialogParamBlock *aParamBlock,
nsIWebBrowserPrint *aWebBrowserPrint,
nsIPrintSettings* aPS,
const char *aChromeURL)
{
NS_ENSURE_ARG(aParamBlock);
NS_ENSURE_ARG(aPS);
NS_ENSURE_ARG(aChromeURL);
if (!mWatcher)
return NS_ERROR_FAILURE;
// get a parent, if at all possible
// (though we'd rather this didn't fail, it's OK if it does. so there's
// no failure or null check.)
nsCOMPtr<mozIDOMWindowProxy> activeParent;
if (!aParent)
{
mWatcher->GetActiveWindow(getter_AddRefs(activeParent));
aParent = activeParent;
}
// create a nsIMutableArray of the parameters
// being passed to the window
nsCOMPtr<nsIMutableArray> array = nsArray::Create();
nsCOMPtr<nsISupports> psSupports(do_QueryInterface(aPS));
NS_ASSERTION(psSupports, "PrintSettings must be a supports");
array->AppendElement(psSupports, /*weak =*/ false);
if (aWebBrowserPrint) {
nsCOMPtr<nsISupports> wbpSupports(do_QueryInterface(aWebBrowserPrint));
NS_ASSERTION(wbpSupports, "nsIWebBrowserPrint must be a supports");
array->AppendElement(wbpSupports, /*weak =*/ false);
}
nsCOMPtr<nsISupports> blkSupps(do_QueryInterface(aParamBlock));
NS_ASSERTION(blkSupps, "IOBlk must be a supports");
array->AppendElement(blkSupps, /*weak =*/ false);
nsCOMPtr<mozIDOMWindowProxy> dialog;
nsresult rv = mWatcher->OpenWindow(aParent, aChromeURL, "_blank",
"centerscreen,chrome,modal,titlebar", array,
getter_AddRefs(dialog));
// if aWebBrowserPrint is not null then we are printing
// so we want to pass back NS_ERROR_ABORT on cancel
if (NS_SUCCEEDED(rv) && aWebBrowserPrint)
{
int32_t status;
aParamBlock->GetInt(0, &status);
return status == 0?NS_ERROR_ABORT:NS_OK;
}
return rv;
}
//////////////////////////////////////////////////////////////////////
// nsIWebProgressListener
//////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsPrintingPromptService::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
{
if ((aStateFlags & STATE_STOP) && mWebProgressListener) {
mWebProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
if (mPrintProgress) {
mPrintProgress->CloseProgressDialog(true);
}
mPrintProgress = nullptr;
mWebProgressListener = nullptr;
}
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
{
if (mWebProgressListener) {
return mWebProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
}
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
{
if (mWebProgressListener) {
return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags);
}
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const char16_t *aMessage)
{
if (mWebProgressListener) {
return mWebProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
}
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptService::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
{
if (mWebProgressListener) {
return mWebProgressListener->OnSecurityChange(aWebProgress, aRequest, state);
}
return NS_OK;
}

View file

@ -0,0 +1,58 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintingPromptService_h
#define __nsPrintingPromptService_h
// {E042570C-62DE-4bb6-A6E0-798E3C07B4DF}
#define NS_PRINTINGPROMPTSERVICE_CID \
{0xe042570c, 0x62de, 0x4bb6, { 0xa6, 0xe0, 0x79, 0x8e, 0x3c, 0x7, 0xb4, 0xdf}}
#define NS_PRINTINGPROMPTSERVICE_CONTRACTID \
"@mozilla.org/embedcomp/printingprompt-service;1"
#include "nsCOMPtr.h"
#include "nsIPrintingPromptService.h"
#include "nsPIPromptService.h"
#include "nsIWindowWatcher.h"
// Printing Progress Includes
#include "nsPrintProgress.h"
#include "nsPrintProgressParams.h"
#include "nsIWebProgressListener.h"
class nsIDOMWindow;
class nsIDialogParamBlock;
class nsPrintingPromptService: public nsIPrintingPromptService,
public nsIWebProgressListener
{
public:
nsPrintingPromptService();
nsresult Init();
NS_DECL_NSIPRINTINGPROMPTSERVICE
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_ISUPPORTS
protected:
virtual ~nsPrintingPromptService();
private:
nsresult DoDialog(mozIDOMWindowProxy *aParent,
nsIDialogParamBlock *aParamBlock,
nsIWebBrowserPrint *aWebBrowserPrint,
nsIPrintSettings* aPS,
const char *aChromeURL);
nsCOMPtr<nsIWindowWatcher> mWatcher;
nsCOMPtr<nsIPrintProgress> mPrintProgress;
nsCOMPtr<nsIWebProgressListener> mWebProgressListener;
};
#endif

View file

@ -0,0 +1,18 @@
# -*- 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/.
UNIFIED_SOURCES += [
'nsPrintDialogUtil.cpp',
'nsPrintingPromptService.cpp',
'nsPrintProgress.cpp',
'nsPrintProgressParams.cpp',
]
EXPORTS += [
'nsPrintDialogUtil.h',
]
FINAL_LIBRARY = 'xul'

View file

@ -0,0 +1,854 @@
/* -*- Mode: C++; 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/. */
/* -------------------------------------------------------------------
To Build This:
You need to add this to the the makefile.win in mozilla/dom/base:
.\$(OBJDIR)\nsFlyOwnPrintDialog.obj \
And this to the makefile.win in mozilla/content/build:
WIN_LIBS= \
winspool.lib \
comctl32.lib \
comdlg32.lib
---------------------------------------------------------------------- */
#include "plstr.h"
#include <windows.h>
#include <tchar.h>
#include <unknwn.h>
#include <commdlg.h>
#include "nsIWebBrowserPrint.h"
#include "nsString.h"
#include "nsIServiceManager.h"
#include "nsReadableUtils.h"
#include "nsIPrintSettings.h"
#include "nsIPrintSettingsWin.h"
#include "nsIPrinterEnumerator.h"
#include "nsRect.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsCRT.h"
#include "prenv.h" /* for PR_GetEnv */
#include <windows.h>
#include <winspool.h>
// For Localization
#include "nsIStringBundle.h"
// For NS_CopyUnicodeToNative
#include "nsNativeCharsetUtils.h"
// This is for extending the dialog
#include <dlgs.h>
#include "nsWindowsHelpers.h"
#include "WinUtils.h"
// Default labels for the radio buttons
static const char* kAsLaidOutOnScreenStr = "As &laid out on the screen";
static const char* kTheSelectedFrameStr = "The selected &frame";
static const char* kEachFrameSeparately = "&Each frame separately";
//-----------------------------------------------
// Global Data
//-----------------------------------------------
// Identifies which new radio btn was cliked on
static UINT gFrameSelectedRadioBtn = 0;
// Indicates whether the native print dialog was successfully extended
static bool gDialogWasExtended = false;
#define PRINTDLG_PROPERTIES "chrome://global/locale/printdialog.properties"
static HWND gParentWnd = nullptr;
//----------------------------------------------------------------------------------
// Return localized bundle for resource strings
static nsresult
GetLocalizedBundle(const char * aPropFileName, nsIStringBundle** aStrBundle)
{
NS_ENSURE_ARG_POINTER(aPropFileName);
NS_ENSURE_ARG_POINTER(aStrBundle);
nsresult rv;
nsCOMPtr<nsIStringBundle> bundle;
// Create bundle
nsCOMPtr<nsIStringBundleService> stringService =
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && stringService) {
rv = stringService->CreateBundle(aPropFileName, aStrBundle);
}
return rv;
}
//--------------------------------------------------------
// Return localized string
static nsresult
GetLocalizedString(nsIStringBundle* aStrBundle, const char* aKey, nsString& oVal)
{
NS_ENSURE_ARG_POINTER(aStrBundle);
NS_ENSURE_ARG_POINTER(aKey);
// Determine default label from string bundle
nsXPIDLString valUni;
nsAutoString key;
key.AssignWithConversion(aKey);
nsresult rv = aStrBundle->GetStringFromName(key.get(), getter_Copies(valUni));
if (NS_SUCCEEDED(rv) && valUni) {
oVal.Assign(valUni);
} else {
oVal.Truncate();
}
return rv;
}
//--------------------------------------------------------
// Set a multi-byte string in the control
static void SetTextOnWnd(HWND aControl, const nsString& aStr)
{
nsAutoCString text;
if (NS_SUCCEEDED(NS_CopyUnicodeToNative(aStr, text))) {
::SetWindowText(aControl, text.get());
}
}
//--------------------------------------------------------
// Will get the control and localized string by "key"
static void SetText(HWND aParent,
UINT aId,
nsIStringBundle* aStrBundle,
const char* aKey)
{
HWND wnd = GetDlgItem (aParent, aId);
if (!wnd) {
return;
}
nsAutoString str;
nsresult rv = GetLocalizedString(aStrBundle, aKey, str);
if (NS_SUCCEEDED(rv)) {
SetTextOnWnd(wnd, str);
}
}
//--------------------------------------------------------
static void SetRadio(HWND aParent,
UINT aId,
bool aIsSet,
bool isEnabled = true)
{
HWND wnd = ::GetDlgItem (aParent, aId);
if (!wnd) {
return;
}
if (!isEnabled) {
::EnableWindow(wnd, FALSE);
return;
}
::EnableWindow(wnd, TRUE);
::SendMessage(wnd, BM_SETCHECK, (WPARAM)aIsSet, (LPARAM)0);
}
//--------------------------------------------------------
static void SetRadioOfGroup(HWND aDlg, int aRadId)
{
int radioIds[] = {rad4, rad5, rad6};
int numRads = 3;
for (int i=0;i<numRads;i++) {
HWND radWnd = ::GetDlgItem(aDlg, radioIds[i]);
if (radWnd != nullptr) {
::SendMessage(radWnd, BM_SETCHECK, (WPARAM)(radioIds[i] == aRadId), (LPARAM)0);
}
}
}
//--------------------------------------------------------
typedef struct {
const char * mKeyStr;
long mKeyId;
} PropKeyInfo;
// These are the control ids used in the dialog and
// defined by MS-Windows in commdlg.h
static PropKeyInfo gAllPropKeys[] = {
{"printFramesTitleWindows", grp3},
{"asLaidOutWindows", rad4},
{"selectedFrameWindows", rad5},
{"separateFramesWindows", rad6},
{nullptr, 0}};
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Get the absolute coords of the child windows relative
// to its parent window
static void GetLocalRect(HWND aWnd, RECT& aRect, HWND aParent)
{
::GetWindowRect(aWnd, &aRect);
// MapWindowPoints converts screen coordinates to client coordinates.
// It works correctly in both left-to-right and right-to-left windows.
::MapWindowPoints(nullptr, aParent, (LPPOINT)&aRect, 2);
}
//--------------------------------------------------------
// Show or Hide the control
static void Show(HWND aWnd, bool bState)
{
if (aWnd) {
::ShowWindow(aWnd, bState?SW_SHOW:SW_HIDE);
}
}
//--------------------------------------------------------
// Create a child window "control"
static HWND CreateControl(LPCTSTR aType,
DWORD aStyle,
HINSTANCE aHInst,
HWND aHdlg,
int aId,
const nsAString& aStr,
const nsIntRect& aRect)
{
nsAutoCString str;
if (NS_FAILED(NS_CopyUnicodeToNative(aStr, str)))
return nullptr;
HWND hWnd = ::CreateWindow (aType, str.get(),
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | aStyle,
aRect.x, aRect.y, aRect.width, aRect.height,
(HWND)aHdlg, (HMENU)(intptr_t)aId,
aHInst, nullptr);
if (hWnd == nullptr) return nullptr;
// get the native font for the dialog and
// set it into the new control
HFONT hFont = (HFONT)::SendMessage(aHdlg, WM_GETFONT, (WPARAM)0, (LPARAM)0);
if (hFont != nullptr) {
::SendMessage(hWnd, WM_SETFONT, (WPARAM) hFont, (LPARAM)0);
}
return hWnd;
}
//--------------------------------------------------------
// Create a Radio Button
static HWND CreateRadioBtn(HINSTANCE aHInst,
HWND aHdlg,
int aId,
const char* aStr,
const nsIntRect& aRect)
{
nsString cStr;
cStr.AssignWithConversion(aStr);
return CreateControl("BUTTON", BS_RADIOBUTTON, aHInst, aHdlg, aId, cStr, aRect);
}
//--------------------------------------------------------
// Create a Group Box
static HWND CreateGroupBox(HINSTANCE aHInst,
HWND aHdlg,
int aId,
const nsAString& aStr,
const nsIntRect& aRect)
{
return CreateControl("BUTTON", BS_GROUPBOX, aHInst, aHdlg, aId, aStr, aRect);
}
//--------------------------------------------------------
// Localizes and initializes the radio buttons and group
static void InitializeExtendedDialog(HWND hdlg, int16_t aHowToEnableFrameUI)
{
MOZ_ASSERT(aHowToEnableFrameUI != nsIPrintSettings::kFrameEnableNone,
"should not be called");
// Localize the new controls in the print dialog
nsCOMPtr<nsIStringBundle> strBundle;
if (NS_SUCCEEDED(GetLocalizedBundle(PRINTDLG_PROPERTIES, getter_AddRefs(strBundle)))) {
int32_t i = 0;
while (gAllPropKeys[i].mKeyStr != nullptr) {
SetText(hdlg, gAllPropKeys[i].mKeyId, strBundle, gAllPropKeys[i].mKeyStr);
i++;
}
}
// Set up radio buttons
if (aHowToEnableFrameUI == nsIPrintSettings::kFrameEnableAll) {
SetRadio(hdlg, rad4, false);
SetRadio(hdlg, rad5, true);
SetRadio(hdlg, rad6, false);
// set default so user doesn't have to actually press on it
gFrameSelectedRadioBtn = rad5;
} else { // nsIPrintSettings::kFrameEnableAsIsAndEach
SetRadio(hdlg, rad4, false);
SetRadio(hdlg, rad5, false, false);
SetRadio(hdlg, rad6, true);
// set default so user doesn't have to actually press on it
gFrameSelectedRadioBtn = rad6;
}
}
//--------------------------------------------------------
// Special Hook Procedure for handling the print dialog messages
static UINT CALLBACK PrintHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
if (uiMsg == WM_COMMAND) {
UINT id = LOWORD(wParam);
if (id == rad4 || id == rad5 || id == rad6) {
gFrameSelectedRadioBtn = id;
SetRadioOfGroup(hdlg, id);
}
} else if (uiMsg == WM_INITDIALOG) {
PRINTDLG * printDlg = (PRINTDLG *)lParam;
if (printDlg == nullptr) return 0L;
int16_t howToEnableFrameUI = (int16_t)printDlg->lCustData;
// don't add frame options if they would be disabled anyway
// because there are no frames
if (howToEnableFrameUI == nsIPrintSettings::kFrameEnableNone)
return TRUE;
HINSTANCE hInst = (HINSTANCE)::GetWindowLongPtr(hdlg, GWLP_HINSTANCE);
if (hInst == nullptr) return 0L;
// Start by getting the local rects of several of the controls
// so we can calculate where the new controls are
HWND wnd = ::GetDlgItem(hdlg, grp1);
if (wnd == nullptr) return 0L;
RECT dlgRect;
GetLocalRect(wnd, dlgRect, hdlg);
wnd = ::GetDlgItem(hdlg, rad1); // this is the top control "All"
if (wnd == nullptr) return 0L;
RECT rad1Rect;
GetLocalRect(wnd, rad1Rect, hdlg);
wnd = ::GetDlgItem(hdlg, rad2); // this is the bottom control "Selection"
if (wnd == nullptr) return 0L;
RECT rad2Rect;
GetLocalRect(wnd, rad2Rect, hdlg);
wnd = ::GetDlgItem(hdlg, rad3); // this is the middle control "Pages"
if (wnd == nullptr) return 0L;
RECT rad3Rect;
GetLocalRect(wnd, rad3Rect, hdlg);
HWND okWnd = ::GetDlgItem(hdlg, IDOK);
if (okWnd == nullptr) return 0L;
RECT okRect;
GetLocalRect(okWnd, okRect, hdlg);
wnd = ::GetDlgItem(hdlg, grp4); // this is the "Print range" groupbox
if (wnd == nullptr) return 0L;
RECT prtRect;
GetLocalRect(wnd, prtRect, hdlg);
// calculate various different "gaps" for layout purposes
int rbGap = rad3Rect.top - rad1Rect.bottom; // gap between radiobtns
int grpBotGap = dlgRect.bottom - rad2Rect.bottom; // gap from bottom rb to bottom of grpbox
int grpGap = dlgRect.top - prtRect.bottom ; // gap between group boxes
int top = dlgRect.bottom + grpGap;
int radHgt = rad1Rect.bottom - rad1Rect.top + 1; // top of new group box
int y = top+(rad1Rect.top-dlgRect.top); // starting pos of first radio
int rbWidth = dlgRect.right - rad1Rect.left - 5; // measure from rb left to the edge of the groupbox
// (5 is arbitrary)
nsIntRect rect;
// Create and position the radio buttons
//
// If any one control cannot be created then
// hide the others and bail out
//
rect.SetRect(rad1Rect.left, y, rbWidth,radHgt);
HWND rad4Wnd = CreateRadioBtn(hInst, hdlg, rad4, kAsLaidOutOnScreenStr, rect);
if (rad4Wnd == nullptr) return 0L;
y += radHgt + rbGap;
rect.SetRect(rad1Rect.left, y, rbWidth, radHgt);
HWND rad5Wnd = CreateRadioBtn(hInst, hdlg, rad5, kTheSelectedFrameStr, rect);
if (rad5Wnd == nullptr) {
Show(rad4Wnd, FALSE); // hide
return 0L;
}
y += radHgt + rbGap;
rect.SetRect(rad1Rect.left, y, rbWidth, radHgt);
HWND rad6Wnd = CreateRadioBtn(hInst, hdlg, rad6, kEachFrameSeparately, rect);
if (rad6Wnd == nullptr) {
Show(rad4Wnd, FALSE); // hide
Show(rad5Wnd, FALSE); // hide
return 0L;
}
y += radHgt + grpBotGap;
// Create and position the group box
rect.SetRect (dlgRect.left, top, dlgRect.right-dlgRect.left+1, y-top+1);
HWND grpBoxWnd = CreateGroupBox(hInst, hdlg, grp3, NS_LITERAL_STRING("Print Frame"), rect);
if (grpBoxWnd == nullptr) {
Show(rad4Wnd, FALSE); // hide
Show(rad5Wnd, FALSE); // hide
Show(rad6Wnd, FALSE); // hide
return 0L;
}
// Here we figure out the old height of the dlg
// then figure its gap from the old grpbx to the bottom
// then size the dlg
RECT pr, cr;
::GetWindowRect(hdlg, &pr);
::GetClientRect(hdlg, &cr);
int dlgHgt = (cr.bottom - cr.top) + 1;
int bottomGap = dlgHgt - okRect.bottom;
pr.bottom += (dlgRect.bottom-dlgRect.top) + grpGap + 1 - (dlgHgt-dlgRect.bottom) + bottomGap;
::SetWindowPos(hdlg, nullptr, pr.left, pr.top, pr.right-pr.left+1, pr.bottom-pr.top+1,
SWP_NOMOVE|SWP_NOREDRAW|SWP_NOZORDER);
// figure out the new height of the dialog
::GetClientRect(hdlg, &cr);
dlgHgt = (cr.bottom - cr.top) + 1;
// Reposition the OK and Cancel btns
int okHgt = okRect.bottom - okRect.top + 1;
::SetWindowPos(okWnd, nullptr, okRect.left, dlgHgt-bottomGap-okHgt, 0, 0,
SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER);
HWND cancelWnd = ::GetDlgItem(hdlg, IDCANCEL);
if (cancelWnd == nullptr) return 0L;
RECT cancelRect;
GetLocalRect(cancelWnd, cancelRect, hdlg);
int cancelHgt = cancelRect.bottom - cancelRect.top + 1;
::SetWindowPos(cancelWnd, nullptr, cancelRect.left, dlgHgt-bottomGap-cancelHgt, 0, 0,
SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER);
// localize and initialize the groupbox and radiobuttons
InitializeExtendedDialog(hdlg, howToEnableFrameUI);
// Looks like we were able to extend the dialog
gDialogWasExtended = true;
return TRUE;
}
return 0L;
}
//----------------------------------------------------------------------------------
// Returns a Global Moveable Memory Handle to a DevMode
// from the Printer by the name of aPrintName
//
// NOTE:
// This function assumes that aPrintName has already been converted from
// unicode
//
static nsReturnRef<nsHGLOBAL>
CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName,
nsIPrintSettings* aPS)
{
nsHPRINTER hPrinter = nullptr;
// const cast kludge for silly Win32 api's
LPWSTR printName = const_cast<wchar_t*>(static_cast<const wchar_t*>(aPrintName.get()));
BOOL status = ::OpenPrinterW(printName, &hPrinter, nullptr);
if (!status) {
return nsReturnRef<nsHGLOBAL>();
}
// Make sure hPrinter is closed on all paths
nsAutoPrinter autoPrinter(hPrinter);
// Get the buffer size
LONG needed = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, nullptr,
nullptr, 0);
if (needed < 0) {
return nsReturnRef<nsHGLOBAL>();
}
// Allocate a buffer of the correct size.
nsAutoDevMode newDevMode((LPDEVMODEW)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY,
needed));
if (!newDevMode) {
return nsReturnRef<nsHGLOBAL>();
}
nsHGLOBAL hDevMode = ::GlobalAlloc(GHND, needed);
nsAutoGlobalMem globalDevMode(hDevMode);
if (!hDevMode) {
return nsReturnRef<nsHGLOBAL>();
}
LONG ret = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, newDevMode,
nullptr, DM_OUT_BUFFER);
if (ret != IDOK) {
return nsReturnRef<nsHGLOBAL>();
}
// Lock memory and copy contents from DEVMODE (current printer)
// to Global Memory DEVMODE
LPDEVMODEW devMode = (DEVMODEW *)::GlobalLock(hDevMode);
if (!devMode) {
return nsReturnRef<nsHGLOBAL>();
}
memcpy(devMode, newDevMode.get(), needed);
// Initialize values from the PrintSettings
nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aPS);
MOZ_ASSERT(psWin);
psWin->CopyToNative(devMode);
// Sets back the changes we made to the DevMode into the Printer Driver
ret = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, devMode, devMode,
DM_IN_BUFFER | DM_OUT_BUFFER);
if (ret != IDOK) {
::GlobalUnlock(hDevMode);
return nsReturnRef<nsHGLOBAL>();
}
::GlobalUnlock(hDevMode);
return globalDevMode.out();
}
//------------------------------------------------------------------
// helper
static void GetDefaultPrinterNameFromGlobalPrinters(nsXPIDLString &printerName)
{
nsCOMPtr<nsIPrinterEnumerator> prtEnum = do_GetService("@mozilla.org/gfx/printerenumerator;1");
if (prtEnum) {
prtEnum->GetDefaultPrinterName(getter_Copies(printerName));
}
}
// Determine whether we have a completely native dialog
// or whether we cshould extend it
static bool ShouldExtendPrintDialog()
{
nsresult rv;
nsCOMPtr<nsIPrefService> prefs =
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, true);
nsCOMPtr<nsIPrefBranch> prefBranch;
rv = prefs->GetBranch(nullptr, getter_AddRefs(prefBranch));
NS_ENSURE_SUCCESS(rv, true);
bool result;
rv = prefBranch->GetBoolPref("print.extend_native_print_dialog", &result);
NS_ENSURE_SUCCESS(rv, true);
return result;
}
//------------------------------------------------------------------
// Displays the native Print Dialog
static nsresult
ShowNativePrintDialog(HWND aHWnd,
nsIPrintSettings* aPrintSettings)
{
//NS_ENSURE_ARG_POINTER(aHWnd);
NS_ENSURE_ARG_POINTER(aPrintSettings);
gDialogWasExtended = false;
// Get the Print Name to be used
nsXPIDLString printerName;
aPrintSettings->GetPrinterName(getter_Copies(printerName));
// If there is no name then use the default printer
if (printerName.IsEmpty()) {
GetDefaultPrinterNameFromGlobalPrinters(printerName);
} else {
HANDLE hPrinter = nullptr;
if(!::OpenPrinterW(const_cast<wchar_t*>(static_cast<const wchar_t*>(printerName.get())),
&hPrinter, nullptr)) {
// If the last used printer is not found, we should use default printer.
GetDefaultPrinterNameFromGlobalPrinters(printerName);
} else {
::ClosePrinter(hPrinter);
}
}
// Now create a DEVNAMES struct so the the dialog is initialized correctly.
uint32_t len = printerName.Length();
nsHGLOBAL hDevNames = ::GlobalAlloc(GHND, sizeof(wchar_t) * (len + 1)
+ sizeof(DEVNAMES));
nsAutoGlobalMem autoDevNames(hDevNames);
if (!hDevNames) {
return NS_ERROR_OUT_OF_MEMORY;
}
DEVNAMES* pDevNames = (DEVNAMES*)::GlobalLock(hDevNames);
if (!pDevNames) {
return NS_ERROR_FAILURE;
}
pDevNames->wDriverOffset = sizeof(DEVNAMES)/sizeof(wchar_t);
pDevNames->wDeviceOffset = sizeof(DEVNAMES)/sizeof(wchar_t);
pDevNames->wOutputOffset = sizeof(DEVNAMES)/sizeof(wchar_t)+len;
pDevNames->wDefault = 0;
memcpy(pDevNames+1, printerName, (len + 1) * sizeof(wchar_t));
::GlobalUnlock(hDevNames);
// Create a Moveable Memory Object that holds a new DevMode
// from the Printer Name
// The PRINTDLG.hDevMode requires that it be a moveable memory object
// NOTE: autoDevMode is automatically freed when any error occurred
nsAutoGlobalMem autoDevMode(CreateGlobalDevModeAndInit(printerName, aPrintSettings));
// Prepare to Display the Print Dialog
PRINTDLGW prntdlg;
memset(&prntdlg, 0, sizeof(PRINTDLGW));
prntdlg.lStructSize = sizeof(prntdlg);
prntdlg.hwndOwner = aHWnd;
prntdlg.hDevMode = autoDevMode.get();
prntdlg.hDevNames = hDevNames;
prntdlg.hDC = nullptr;
prntdlg.Flags = PD_ALLPAGES | PD_RETURNIC |
PD_USEDEVMODECOPIESANDCOLLATE | PD_COLLATE;
// if there is a current selection then enable the "Selection" radio button
int16_t howToEnableFrameUI = nsIPrintSettings::kFrameEnableNone;
bool isOn;
aPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &isOn);
if (!isOn) {
prntdlg.Flags |= PD_NOSELECTION;
}
aPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI);
int32_t pg = 1;
aPrintSettings->GetStartPageRange(&pg);
prntdlg.nFromPage = pg;
aPrintSettings->GetEndPageRange(&pg);
prntdlg.nToPage = pg;
prntdlg.nMinPage = 1;
prntdlg.nMaxPage = 0xFFFF;
prntdlg.nCopies = 1;
prntdlg.lpfnSetupHook = nullptr;
prntdlg.lpSetupTemplateName = nullptr;
prntdlg.hPrintTemplate = nullptr;
prntdlg.hSetupTemplate = nullptr;
prntdlg.hInstance = nullptr;
prntdlg.lpPrintTemplateName = nullptr;
if (!ShouldExtendPrintDialog()) {
prntdlg.lCustData = 0;
prntdlg.lpfnPrintHook = nullptr;
} else {
// Set up print dialog "hook" procedure for extending the dialog
prntdlg.lCustData = (DWORD)howToEnableFrameUI;
prntdlg.lpfnPrintHook = (LPPRINTHOOKPROC)PrintHookProc;
prntdlg.Flags |= PD_ENABLEPRINTHOOK;
}
BOOL result;
{
mozilla::widget::WinUtils::AutoSystemDpiAware dpiAwareness;
result = ::PrintDlgW(&prntdlg);
}
if (TRUE == result) {
// check to make sure we don't have any nullptr pointers
NS_ENSURE_TRUE(aPrintSettings && prntdlg.hDevMode, NS_ERROR_FAILURE);
if (prntdlg.hDevNames == nullptr) {
return NS_ERROR_FAILURE;
}
// Lock the deviceNames and check for nullptr
DEVNAMES *devnames = (DEVNAMES *)::GlobalLock(prntdlg.hDevNames);
if (devnames == nullptr) {
return NS_ERROR_FAILURE;
}
char16_t* device = &(((char16_t *)devnames)[devnames->wDeviceOffset]);
char16_t* driver = &(((char16_t *)devnames)[devnames->wDriverOffset]);
// Check to see if the "Print To File" control is checked
// then take the name from devNames and set it in the PrintSettings
//
// NOTE:
// As per Microsoft SDK documentation the returned value offset from
// devnames->wOutputOffset is either "FILE:" or nullptr
// if the "Print To File" checkbox is checked it MUST be "FILE:"
// We assert as an extra safety check.
if (prntdlg.Flags & PD_PRINTTOFILE) {
char16ptr_t fileName = &(((wchar_t *)devnames)[devnames->wOutputOffset]);
NS_ASSERTION(wcscmp(fileName, L"FILE:") == 0, "FileName must be `FILE:`");
aPrintSettings->SetToFileName(fileName);
aPrintSettings->SetPrintToFile(true);
} else {
// clear "print to file" info
aPrintSettings->SetPrintToFile(false);
aPrintSettings->SetToFileName(nullptr);
}
nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(aPrintSettings));
if (!psWin) {
return NS_ERROR_FAILURE;
}
// Setup local Data members
psWin->SetDeviceName(device);
psWin->SetDriverName(driver);
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
wprintf(L"printer: driver %s, device %s flags: %d\n", driver, device, prntdlg.Flags);
#endif
// fill the print options with the info from the dialog
aPrintSettings->SetPrinterName(device);
if (prntdlg.Flags & PD_SELECTION) {
aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSelection);
} else if (prntdlg.Flags & PD_PAGENUMS) {
aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeSpecifiedPageRange);
aPrintSettings->SetStartPageRange(prntdlg.nFromPage);
aPrintSettings->SetEndPageRange(prntdlg.nToPage);
} else { // (prntdlg.Flags & PD_ALLPAGES)
aPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages);
}
if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) {
// make sure the dialog got extended
if (gDialogWasExtended) {
// check to see about the frame radio buttons
switch (gFrameSelectedRadioBtn) {
case rad4:
aPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs);
break;
case rad5:
aPrintSettings->SetPrintFrameType(nsIPrintSettings::kSelectedFrame);
break;
case rad6:
aPrintSettings->SetPrintFrameType(nsIPrintSettings::kEachFrameSep);
break;
} // switch
} else {
// if it didn't get extended then have it default to printing
// each frame separately
aPrintSettings->SetPrintFrameType(nsIPrintSettings::kEachFrameSep);
}
} else {
aPrintSettings->SetPrintFrameType(nsIPrintSettings::kNoFrames);
}
// Unlock DeviceNames
::GlobalUnlock(prntdlg.hDevNames);
// Transfer the settings from the native data to the PrintSettings
LPDEVMODEW devMode = (LPDEVMODEW)::GlobalLock(prntdlg.hDevMode);
if (!devMode || !prntdlg.hDC) {
return NS_ERROR_FAILURE;
}
psWin->SetDevMode(devMode); // copies DevMode
psWin->CopyFromNative(prntdlg.hDC, devMode);
::GlobalUnlock(prntdlg.hDevMode);
::DeleteDC(prntdlg.hDC);
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
bool printSelection = prntdlg.Flags & PD_SELECTION;
bool printAllPages = prntdlg.Flags & PD_ALLPAGES;
bool printNumPages = prntdlg.Flags & PD_PAGENUMS;
int32_t fromPageNum = 0;
int32_t toPageNum = 0;
if (printNumPages) {
fromPageNum = prntdlg.nFromPage;
toPageNum = prntdlg.nToPage;
}
if (printSelection) {
printf("Printing the selection\n");
} else if (printAllPages) {
printf("Printing all the pages\n");
} else {
printf("Printing from page no. %d to %d\n", fromPageNum, toPageNum);
}
#endif
} else {
::SetFocus(aHWnd);
aPrintSettings->SetIsCancelled(true);
return NS_ERROR_ABORT;
}
return NS_OK;
}
//------------------------------------------------------------------
static void
PrepareForPrintDialog(nsIWebBrowserPrint* aWebBrowserPrint, nsIPrintSettings* aPS)
{
NS_ASSERTION(aWebBrowserPrint, "Can't be null");
NS_ASSERTION(aPS, "Can't be null");
bool isFramesetDocument;
bool isFramesetFrameSelected;
bool isIFrameSelected;
bool isRangeSelection;
aWebBrowserPrint->GetIsFramesetDocument(&isFramesetDocument);
aWebBrowserPrint->GetIsFramesetFrameSelected(&isFramesetFrameSelected);
aWebBrowserPrint->GetIsIFrameSelected(&isIFrameSelected);
aWebBrowserPrint->GetIsRangeSelection(&isRangeSelection);
// Setup print options for UI
if (isFramesetDocument) {
if (isFramesetFrameSelected) {
aPS->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll);
} else {
aPS->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach);
}
} else {
aPS->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone);
}
// Now determine how to set up the Frame print UI
aPS->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isRangeSelection || isIFrameSelected);
}
//----------------------------------------------------------------------------------
//-- Show Print Dialog
//----------------------------------------------------------------------------------
nsresult NativeShowPrintDialog(HWND aHWnd,
nsIWebBrowserPrint* aWebBrowserPrint,
nsIPrintSettings* aPrintSettings)
{
PrepareForPrintDialog(aWebBrowserPrint, aPrintSettings);
nsresult rv = ShowNativePrintDialog(aHWnd, aPrintSettings);
if (aHWnd) {
::DestroyWindow(aHWnd);
}
return rv;
}

View file

@ -0,0 +1,12 @@
/* -*- Mode: C++; 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/. */
#ifndef nsFlyOwnDialog_h___
#define nsFlyOwnDialog_h___
nsresult NativeShowPrintDialog(HWND aHWnd,
nsIWebBrowserPrint* aWebBrowserPrint,
nsIPrintSettings* aPrintSettings);
#endif /* nsFlyOwnDialog_h___ */

View file

@ -0,0 +1,293 @@
/* -*- Mode: C++; 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 "nsPrintProgress.h"
#include "nsArray.h"
#include "nsIBaseWindow.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIXULWindow.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsPIDOMWindow.h"
#if 0
NS_IMPL_ADDREF(nsPrintProgress)
NS_IMPL_RELEASE(nsPrintProgress)
#else
NS_IMETHODIMP_(MozExternalRefCountType) nsPrintProgress::AddRef(void)
{
NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
nsrefcnt count;
count = ++mRefCnt;
//NS_LOG_ADDREF(this, count, "nsPrintProgress", sizeof(*this));
return count;
}
NS_IMETHODIMP_(MozExternalRefCountType) nsPrintProgress::Release(void)
{
nsrefcnt count;
NS_PRECONDITION(0 != mRefCnt, "dup release");
count = --mRefCnt;
//NS_LOG_RELEASE(this, count, "nsPrintProgress");
if (0 == count) {
mRefCnt = 1; /* stabilize */
/* enable this to find non-threadsafe destructors: */
/* NS_ASSERT_OWNINGTHREAD(nsPrintProgress); */
delete this;
return 0;
}
return count;
}
#endif
NS_INTERFACE_MAP_BEGIN(nsPrintProgress)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrintStatusFeedback)
NS_INTERFACE_MAP_ENTRY(nsIPrintProgress)
NS_INTERFACE_MAP_ENTRY(nsIPrintStatusFeedback)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_END_THREADSAFE
nsPrintProgress::nsPrintProgress()
{
m_closeProgress = false;
m_processCanceled = false;
m_pendingStateFlags = -1;
m_pendingStateValue = NS_OK;
}
nsPrintProgress::~nsPrintProgress()
{
(void)ReleaseListeners();
}
NS_IMETHODIMP nsPrintProgress::OpenProgressDialog(mozIDOMWindowProxy *parent,
const char *dialogURL,
nsISupports *parameters,
nsIObserver *openDialogObserver,
bool *notifyOnOpen)
{
*notifyOnOpen = true;
m_observer = openDialogObserver;
nsresult rv = NS_ERROR_FAILURE;
if (m_dialog)
return NS_ERROR_ALREADY_INITIALIZED;
if (!dialogURL || !*dialogURL)
return NS_ERROR_INVALID_ARG;
if (parent)
{
// Set up window.arguments[0]...
nsCOMPtr<nsIMutableArray> array = nsArray::Create();
nsCOMPtr<nsISupportsInterfacePointer> ifptr =
do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
ifptr->SetData(static_cast<nsIPrintProgress*>(this));
ifptr->SetDataIID(&NS_GET_IID(nsIPrintProgress));
array->AppendElement(ifptr, /*weak =*/ false);
array->AppendElement(parameters, /*weak = */ false);
// We will set the opener of the dialog to be the nsIDOMWindow for the
// browser XUL window itself, as opposed to the content. That way, the
// progress window has access to the opener.
nsCOMPtr<nsPIDOMWindowOuter> pParentWindow = nsPIDOMWindowOuter::From(parent);
NS_ENSURE_STATE(pParentWindow);
nsCOMPtr<nsIDocShell> docShell = pParentWindow->GetDocShell();
NS_ENSURE_STATE(docShell);
nsCOMPtr<nsIDocShellTreeOwner> owner;
docShell->GetTreeOwner(getter_AddRefs(owner));
nsCOMPtr<nsIXULWindow> ownerXULWindow = do_GetInterface(owner);
nsCOMPtr<mozIDOMWindowProxy> ownerWindow = do_GetInterface(ownerXULWindow);
NS_ENSURE_STATE(ownerWindow);
nsCOMPtr<nsPIDOMWindowOuter> piOwnerWindow = nsPIDOMWindowOuter::From(ownerWindow);
// Open the dialog.
nsCOMPtr<nsPIDOMWindowOuter> newWindow;
rv = piOwnerWindow->OpenDialog(NS_ConvertASCIItoUTF16(dialogURL),
NS_LITERAL_STRING("_blank"),
NS_LITERAL_STRING("chrome,titlebar,dependent,centerscreen"),
array, getter_AddRefs(newWindow));
}
return rv;
}
NS_IMETHODIMP nsPrintProgress::CloseProgressDialog(bool forceClose)
{
m_closeProgress = true;
// XXX Casting from bool to nsresult
return OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP,
static_cast<nsresult>(forceClose));
}
NS_IMETHODIMP nsPrintProgress::GetPrompter(nsIPrompt **_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = nullptr;
if (! m_closeProgress && m_dialog) {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(m_dialog);
MOZ_ASSERT(window);
return window->GetPrompter(_retval);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsPrintProgress::GetProcessCanceledByUser(bool *aProcessCanceledByUser)
{
NS_ENSURE_ARG_POINTER(aProcessCanceledByUser);
*aProcessCanceledByUser = m_processCanceled;
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::SetProcessCanceledByUser(bool aProcessCanceledByUser)
{
m_processCanceled = aProcessCanceledByUser;
OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::RegisterListener(nsIWebProgressListener * listener)
{
if (!listener) //Nothing to do with a null listener!
return NS_OK;
m_listenerList.AppendObject(listener);
if (m_closeProgress || m_processCanceled)
listener->OnStateChange(nullptr, nullptr,
nsIWebProgressListener::STATE_STOP, NS_OK);
else
{
listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
if (m_pendingStateFlags != -1)
listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::UnregisterListener(nsIWebProgressListener *listener)
{
if (listener)
m_listenerList.RemoveObject(listener);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::DoneIniting()
{
if (m_observer) {
m_observer->Observe(nullptr, nullptr, nullptr);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
{
m_pendingStateFlags = aStateFlags;
m_pendingStateValue = aStatus;
uint32_t count = m_listenerList.Count();
for (uint32_t i = count - 1; i < count; i --)
{
nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
if (progressListener)
progressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
{
uint32_t count = m_listenerList.Count();
for (uint32_t i = count - 1; i < count; i --)
{
nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
if (progressListener)
progressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
{
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const char16_t *aMessage)
{
if (aMessage && *aMessage)
m_pendingStatus = aMessage;
uint32_t count = m_listenerList.Count();
for (uint32_t i = count - 1; i < count; i --)
{
nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
if (progressListener)
progressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
}
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
{
return NS_OK;
}
nsresult nsPrintProgress::ReleaseListeners()
{
m_listenerList.Clear();
return NS_OK;
}
NS_IMETHODIMP nsPrintProgress::ShowStatusString(const char16_t *status)
{
return OnStatusChange(nullptr, nullptr, NS_OK, status);
}
NS_IMETHODIMP nsPrintProgress::StartMeteors()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::StopMeteors()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::ShowProgress(int32_t percent)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::SetDocShell(nsIDocShell *shell, mozIDOMWindowProxy *window)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPrintProgress::CloseWindow()
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View file

@ -0,0 +1,43 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintProgress_h
#define __nsPrintProgress_h
#include "nsIPrintProgress.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsIDOMWindow.h"
#include "nsIPrintStatusFeedback.h"
#include "nsString.h"
#include "nsIWindowWatcher.h"
#include "nsIObserver.h"
class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIPRINTPROGRESS
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSIPRINTSTATUSFEEDBACK
nsPrintProgress();
virtual ~nsPrintProgress();
private:
nsresult ReleaseListeners();
bool m_closeProgress;
bool m_processCanceled;
nsString m_pendingStatus;
int32_t m_pendingStateFlags;
nsresult m_pendingStateValue;
nsCOMPtr<nsIDOMWindow> m_dialog;
nsCOMArray<nsIWebProgressListener> m_listenerList;
nsCOMPtr<nsIObserver> m_observer;
};
#endif

View file

@ -0,0 +1,47 @@
/* -*- Mode: C++; 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 "nsPrintProgressParams.h"
#include "nsReadableUtils.h"
NS_IMPL_ISUPPORTS(nsPrintProgressParams, nsIPrintProgressParams)
nsPrintProgressParams::nsPrintProgressParams()
{
}
nsPrintProgressParams::~nsPrintProgressParams()
{
}
NS_IMETHODIMP nsPrintProgressParams::GetDocTitle(char16_t * *aDocTitle)
{
NS_ENSURE_ARG(aDocTitle);
*aDocTitle = ToNewUnicode(mDocTitle);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgressParams::SetDocTitle(const char16_t * aDocTitle)
{
mDocTitle = aDocTitle;
return NS_OK;
}
NS_IMETHODIMP nsPrintProgressParams::GetDocURL(char16_t * *aDocURL)
{
NS_ENSURE_ARG(aDocURL);
*aDocURL = ToNewUnicode(mDocURL);
return NS_OK;
}
NS_IMETHODIMP nsPrintProgressParams::SetDocURL(const char16_t * aDocURL)
{
mDocURL = aDocURL;
return NS_OK;
}

View file

@ -0,0 +1,27 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintProgressParams_h
#define __nsPrintProgressParams_h
#include "nsIPrintProgressParams.h"
#include "nsString.h"
class nsPrintProgressParams : public nsIPrintProgressParams
{
virtual ~nsPrintProgressParams();
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPRINTPROGRESSPARAMS
nsPrintProgressParams();
private:
nsString mDocTitle;
nsString mDocURL;
};
#endif

View file

@ -0,0 +1,341 @@
/* -*- 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 "nsCOMPtr.h"
#include "nsPrintingPromptService.h"
#include "nsIPrintingPromptService.h"
#include "nsIFactory.h"
#include "nsPIDOMWindow.h"
#include "nsReadableUtils.h"
#include "nsIEmbeddingSiteWindow.h"
#include "nsIServiceManager.h"
#include "nsIWebBrowserChrome.h"
#include "nsIWindowWatcher.h"
#include "nsPrintDialogUtil.h"
// Printing Progress Includes
#include "nsPrintProgress.h"
#include "nsPrintProgressParams.h"
#include "nsIWebProgressListener.h"
// XP Dialog includes
#include "nsArray.h"
#include "nsIDialogParamBlock.h"
#include "nsISupportsUtils.h"
// Includes need to locate the native Window
#include "nsIWidget.h"
#include "nsIBaseWindow.h"
#include "nsIWebBrowserChrome.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocShell.h"
#include "nsIInterfaceRequestorUtils.h"
static const char *kPrintProgressDialogURL = "chrome://global/content/printProgress.xul";
static const char *kPrtPrvProgressDialogURL = "chrome://global/content/printPreviewProgress.xul";
static const char *kPageSetupDialogURL = "chrome://global/content/printPageSetup.xul";
/****************************************************************
************************* ParamBlock ***************************
****************************************************************/
class ParamBlock {
public:
ParamBlock()
{
mBlock = 0;
}
~ParamBlock()
{
NS_IF_RELEASE(mBlock);
}
nsresult Init() {
return CallCreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID, &mBlock);
}
nsIDialogParamBlock * operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { return mBlock; }
operator nsIDialogParamBlock * const () { return mBlock; }
private:
nsIDialogParamBlock *mBlock;
};
//*****************************************************************************
NS_IMPL_ISUPPORTS(nsPrintingPromptService, nsIPrintingPromptService, nsIWebProgressListener)
nsPrintingPromptService::nsPrintingPromptService()
{
}
//-----------------------------------------------------------
nsPrintingPromptService::~nsPrintingPromptService()
{
}
//-----------------------------------------------------------
nsresult
nsPrintingPromptService::Init()
{
nsresult rv;
mWatcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
return rv;
}
//-----------------------------------------------------------
HWND
nsPrintingPromptService::GetHWNDForDOMWindow(mozIDOMWindowProxy *aWindow)
{
nsCOMPtr<nsIWebBrowserChrome> chrome;
// We might be embedded so check this path first
if (mWatcher) {
nsCOMPtr<mozIDOMWindowProxy> fosterParent;
if (!aWindow)
{ // it will be a dependent window. try to find a foster parent.
mWatcher->GetActiveWindow(getter_AddRefs(fosterParent));
aWindow = fosterParent;
}
mWatcher->GetChromeForWindow(aWindow, getter_AddRefs(chrome));
}
if (chrome) {
nsCOMPtr<nsIEmbeddingSiteWindow> site(do_QueryInterface(chrome));
if (site)
{
HWND w;
site->GetSiteWindow(reinterpret_cast<void **>(&w));
return w;
}
}
// Now we might be the Browser so check this path
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
nsCOMPtr<nsIDocShellTreeItem> treeItem =
do_QueryInterface(window->GetDocShell());
if (!treeItem) return nullptr;
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
if (!treeOwner) return nullptr;
nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome(do_GetInterface(treeOwner));
if (!webBrowserChrome) return nullptr;
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(webBrowserChrome));
if (!baseWin) return nullptr;
nsCOMPtr<nsIWidget> widget;
baseWin->GetMainWidget(getter_AddRefs(widget));
if (!widget) return nullptr;
return (HWND)widget->GetNativeData(NS_NATIVE_TMP_WINDOW);
}
///////////////////////////////////////////////////////////////////////////////
// nsIPrintingPromptService
//-----------------------------------------------------------
NS_IMETHODIMP
nsPrintingPromptService::ShowPrintDialog(mozIDOMWindowProxy *parent, nsIWebBrowserPrint *webBrowserPrint, nsIPrintSettings *printSettings)
{
NS_ENSURE_ARG(parent);
HWND hWnd = GetHWNDForDOMWindow(parent);
NS_ASSERTION(hWnd, "Couldn't get native window for PRint Dialog!");
return NativeShowPrintDialog(hWnd, webBrowserPrint, printSettings);
}
NS_IMETHODIMP
nsPrintingPromptService::ShowProgress(mozIDOMWindowProxy* parent,
nsIWebBrowserPrint* webBrowserPrint, // ok to be null
nsIPrintSettings* printSettings, // ok to be null
nsIObserver* openDialogObserver, // ok to be null
bool isForPrinting,
nsIWebProgressListener** webProgressListener,
nsIPrintProgressParams** printProgressParams,
bool* notifyOnOpen)
{
NS_ENSURE_ARG(webProgressListener);
NS_ENSURE_ARG(printProgressParams);
NS_ENSURE_ARG(notifyOnOpen);
*notifyOnOpen = false;
if (mPrintProgress) {
*webProgressListener = nullptr;
*printProgressParams = nullptr;
return NS_ERROR_FAILURE;
}
nsPrintProgress* prtProgress = new nsPrintProgress();
mPrintProgress = prtProgress;
mWebProgressListener = prtProgress;
nsCOMPtr<nsIPrintProgressParams> prtProgressParams = new nsPrintProgressParams();
nsCOMPtr<mozIDOMWindowProxy> parentWindow = parent;
if (mWatcher && !parentWindow) {
mWatcher->GetActiveWindow(getter_AddRefs(parentWindow));
}
if (parentWindow) {
mPrintProgress->OpenProgressDialog(parentWindow,
isForPrinting ? kPrintProgressDialogURL : kPrtPrvProgressDialogURL,
prtProgressParams, openDialogObserver, notifyOnOpen);
}
prtProgressParams.forget(printProgressParams);
NS_ADDREF(*webProgressListener = this);
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPageSetup(mozIDOMWindowProxy *parent, nsIPrintSettings *printSettings, nsIObserver *aObs)
{
NS_ENSURE_ARG(printSettings);
ParamBlock block;
nsresult rv = block.Init();
if (NS_FAILED(rv))
return rv;
block->SetInt(0, 0);
rv = DoDialog(parent, block, printSettings, kPageSetupDialogURL);
// if aWebBrowserPrint is not null then we are printing
// so we want to pass back NS_ERROR_ABORT on cancel
if (NS_SUCCEEDED(rv))
{
int32_t status;
block->GetInt(0, &status);
return status == 0?NS_ERROR_ABORT:NS_OK;
}
return rv;
}
NS_IMETHODIMP
nsPrintingPromptService::ShowPrinterProperties(mozIDOMWindowProxy *parent, const char16_t *printerName, nsIPrintSettings *printSettings)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//-----------------------------------------------------------
// Helper to Fly XP Dialog
nsresult
nsPrintingPromptService::DoDialog(mozIDOMWindowProxy *aParent,
nsIDialogParamBlock *aParamBlock,
nsIPrintSettings* aPS,
const char *aChromeURL)
{
NS_ENSURE_ARG(aParamBlock);
NS_ENSURE_ARG(aPS);
NS_ENSURE_ARG(aChromeURL);
if (!mWatcher)
return NS_ERROR_FAILURE;
// get a parent, if at all possible
// (though we'd rather this didn't fail, it's OK if it does. so there's
// no failure or null check.)
nsCOMPtr<mozIDOMWindowProxy> activeParent; // retain ownership for method lifetime
if (!aParent)
{
mWatcher->GetActiveWindow(getter_AddRefs(activeParent));
aParent = activeParent;
}
// create a nsIMutableArray of the parameters
// being passed to the window
nsCOMPtr<nsIMutableArray> array = nsArray::Create();
nsCOMPtr<nsISupports> psSupports(do_QueryInterface(aPS));
NS_ASSERTION(psSupports, "PrintSettings must be a supports");
array->AppendElement(psSupports, /*weak =*/ false);
nsCOMPtr<nsISupports> blkSupps(do_QueryInterface(aParamBlock));
NS_ASSERTION(blkSupps, "IOBlk must be a supports");
array->AppendElement(blkSupps, /*weak =*/ false);
nsCOMPtr<mozIDOMWindowProxy> dialog;
nsresult rv = mWatcher->OpenWindow(aParent, aChromeURL, "_blank",
"centerscreen,chrome,modal,titlebar", array,
getter_AddRefs(dialog));
return rv;
}
//////////////////////////////////////////////////////////////////////
// nsIWebProgressListener
//////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsPrintingPromptService::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
{
if ((aStateFlags & STATE_STOP) && mWebProgressListener)
{
mWebProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
if (mPrintProgress)
{
mPrintProgress->CloseProgressDialog(true);
}
mPrintProgress = nullptr;
mWebProgressListener = nullptr;
}
return NS_OK;
}
NS_IMETHODIMP
nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
{
if (mWebProgressListener)
{
return mWebProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
{
if (mWebProgressListener)
{
return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const char16_t *aMessage)
{
if (mWebProgressListener)
{
return mWebProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsPrintingPromptService::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
{
if (mWebProgressListener)
{
return mWebProgressListener->OnSecurityChange(aWebProgress, aRequest, state);
}
return NS_ERROR_FAILURE;
}

View file

@ -0,0 +1,58 @@
/* -*- Mode: C++; 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/. */
#ifndef __nsPrintingPromptService_h
#define __nsPrintingPromptService_h
#include <windows.h>
// {E042570C-62DE-4bb6-A6E0-798E3C07B4DF}
#define NS_PRINTINGPROMPTSERVICE_CID \
{0xe042570c, 0x62de, 0x4bb6, { 0xa6, 0xe0, 0x79, 0x8e, 0x3c, 0x7, 0xb4, 0xdf}}
#define NS_PRINTINGPROMPTSERVICE_CONTRACTID \
"@mozilla.org/embedcomp/printingprompt-service;1"
#include "nsCOMPtr.h"
#include "nsIPrintingPromptService.h"
#include "nsPIPromptService.h"
#include "nsIWindowWatcher.h"
// Printing Progress Includes
#include "nsPrintProgress.h"
#include "nsPrintProgressParams.h"
#include "nsIWebProgressListener.h"
class nsIDOMWindow;
class nsIDialogParamBlock;
class nsPrintingPromptService: public nsIPrintingPromptService,
public nsIWebProgressListener
{
virtual ~nsPrintingPromptService();
public:
nsPrintingPromptService();
nsresult Init();
NS_DECL_ISUPPORTS
NS_DECL_NSIPRINTINGPROMPTSERVICE
NS_DECL_NSIWEBPROGRESSLISTENER
private:
HWND GetHWNDForDOMWindow(mozIDOMWindowProxy *parent);
nsresult DoDialog(mozIDOMWindowProxy *aParent,
nsIDialogParamBlock *aParamBlock,
nsIPrintSettings* aPS,
const char *aChromeURL);
nsCOMPtr<nsIWindowWatcher> mWatcher;
nsCOMPtr<nsIPrintProgress> mPrintProgress;
nsCOMPtr<nsIWebProgressListener> mWebProgressListener;
};
#endif

View file

@ -0,0 +1,90 @@
/* -*- Mode: IDL; tab-width: 8; 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 protocol PContent;
include protocol PWebBrowserPersistResources;
include protocol PWebBrowserPersistSerialize;
include InputStreamParams;
namespace mozilla {
// nsIWebBrowserPersistDocument has attributes which can be read
// synchronously. To avoid using sync IPC for them, the actor sends
// this structure from the child to the parent before the parent actor
// is exposed to XPCOM.
struct WebBrowserPersistDocumentAttrs {
bool isPrivate;
nsCString documentURI;
nsCString baseURI;
nsCString contentType;
nsCString characterSet;
nsString title;
nsString referrer;
nsString contentDisposition;
uint32_t cacheKey;
uint32_t persistFlags;
};
// IPDL doesn't have tuples, so this gives the pair of strings from
// nsIWebBrowserPersistURIMap::getURIMapping a name.
struct WebBrowserPersistURIMapEntry {
nsCString mapFrom;
nsCString mapTo;
};
// nsIWebBrowserPersistURIMap is just copied over IPC as one of these,
// not proxied, to simplify the protocol.
struct WebBrowserPersistURIMap {
WebBrowserPersistURIMapEntry[] mapURIs;
nsCString targetBaseURI;
};
// This remotes nsIWebBrowserPersistDocument and its visitors. The
// lifecycle is a little complicated: the initial document is
// constructed parent->child, but subdocuments are constructed
// child->parent and then passed back. Subdocuments aren't subactors,
// because that would impose a lifetime relationship that doesn't
// exist in the XPIDL; instead they're all managed by the enclosing
// PContent.
protocol PWebBrowserPersistDocument {
manager PContent;
manages PWebBrowserPersistResources;
manages PWebBrowserPersistSerialize;
parent:
// The actor isn't exposed to XPCOM until after it gets one of these
// two messages; see also the state transition rules. The message
// is either a response to the constructor (if it was parent->child)
// or sent after it (if it was child->parent).
async Attributes(WebBrowserPersistDocumentAttrs aAttrs,
OptionalInputStreamParams postData,
FileDescriptor[] postFiles);
async InitFailure(nsresult aStatus);
child:
async SetPersistFlags(uint32_t aNewFlags);
async PWebBrowserPersistResources();
async PWebBrowserPersistSerialize(WebBrowserPersistURIMap aMap,
nsCString aRequestedContentType,
uint32_t aEncoderFlags,
uint32_t aWrapColumn);
async __delete__();
state START:
recv Attributes goto MAIN;
recv InitFailure goto FAILED;
state MAIN:
send SetPersistFlags goto MAIN;
send PWebBrowserPersistResources goto MAIN;
send PWebBrowserPersistSerialize goto MAIN;
send __delete__;
state FAILED:
send __delete__;
};
} // namespace mozilla

View file

@ -0,0 +1,26 @@
/* -*- Mode: IDL; tab-width: 8; 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 protocol PWebBrowserPersistDocument;
namespace mozilla {
// == nsIWebBrowserPersistResourceVisitor
protocol PWebBrowserPersistResources {
manager PWebBrowserPersistDocument;
parent:
async VisitResource(nsCString aURI);
// The actor sent here is in the START state; the parent-side
// receiver will have to wait for it to enter the MAIN state
// before exposing it with a visitDocument call.
async VisitDocument(PWebBrowserPersistDocument aSubDocument);
// This reflects the endVisit method.
async __delete__(nsresult aStatus);
};
} // namespace mozilla

View file

@ -0,0 +1,29 @@
/* -*- Mode: IDL; tab-width: 8; 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 protocol PWebBrowserPersistDocument;
namespace mozilla {
// This actor represents both an nsIWebBrowserPersistWriteCompletion
// and the nsIOutputStream passed with it to the writeContent method.
protocol PWebBrowserPersistSerialize {
manager PWebBrowserPersistDocument;
parent:
// This sends the data with no flow control, so the parent could
// wind up buffering an arbitrarily large amount of data... but
// it's a serialized DOM that's already in memory as DOM nodes, so
// this is at worst just a constant-factor increase in memory usage.
// Also, Chromium does the same thing; see
// content::RenderViewImpl::didSerializeDataForFrame.
async WriteData(uint8_t[] aData);
// This is the onFinish method.
async __delete__(nsCString aContentType,
nsresult aStatus);
};
} // namespace mozilla

View file

@ -0,0 +1,159 @@
/* -*- 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 "WebBrowserPersistDocumentChild.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsIDocument.h"
#include "nsIInputStream.h"
#include "WebBrowserPersistLocalDocument.h"
#include "WebBrowserPersistResourcesChild.h"
#include "WebBrowserPersistSerializeChild.h"
namespace mozilla {
WebBrowserPersistDocumentChild::WebBrowserPersistDocumentChild()
{
}
WebBrowserPersistDocumentChild::~WebBrowserPersistDocumentChild()
{
}
void
WebBrowserPersistDocumentChild::Start(nsIDocument* aDocument)
{
RefPtr<WebBrowserPersistLocalDocument> doc;
if (aDocument) {
doc = new WebBrowserPersistLocalDocument(aDocument);
}
Start(doc);
}
void
WebBrowserPersistDocumentChild::Start(nsIWebBrowserPersistDocument* aDocument)
{
MOZ_ASSERT(!mDocument);
if (!aDocument) {
SendInitFailure(NS_ERROR_FAILURE);
return;
}
WebBrowserPersistDocumentAttrs attrs;
nsCOMPtr<nsIInputStream> postDataStream;
OptionalInputStreamParams postData;
nsTArray<FileDescriptor> postFiles;
#define ENSURE(e) do { \
nsresult rv = (e); \
if (NS_FAILED(rv)) { \
SendInitFailure(rv); \
return; \
} \
} while(0)
ENSURE(aDocument->GetIsPrivate(&(attrs.isPrivate())));
ENSURE(aDocument->GetDocumentURI(attrs.documentURI()));
ENSURE(aDocument->GetBaseURI(attrs.baseURI()));
ENSURE(aDocument->GetContentType(attrs.contentType()));
ENSURE(aDocument->GetCharacterSet(attrs.characterSet()));
ENSURE(aDocument->GetTitle(attrs.title()));
ENSURE(aDocument->GetReferrer(attrs.referrer()));
ENSURE(aDocument->GetContentDisposition(attrs.contentDisposition()));
ENSURE(aDocument->GetCacheKey(&(attrs.cacheKey())));
ENSURE(aDocument->GetPersistFlags(&(attrs.persistFlags())));
ENSURE(aDocument->GetPostData(getter_AddRefs(postDataStream)));
ipc::SerializeInputStream(postDataStream,
postData,
postFiles);
#undef ENSURE
mDocument = aDocument;
SendAttributes(attrs, postData, postFiles);
}
bool
WebBrowserPersistDocumentChild::RecvSetPersistFlags(const uint32_t& aNewFlags)
{
mDocument->SetPersistFlags(aNewFlags);
return true;
}
PWebBrowserPersistResourcesChild*
WebBrowserPersistDocumentChild::AllocPWebBrowserPersistResourcesChild()
{
auto* actor = new WebBrowserPersistResourcesChild();
NS_ADDREF(actor);
return actor;
}
bool
WebBrowserPersistDocumentChild::RecvPWebBrowserPersistResourcesConstructor(PWebBrowserPersistResourcesChild* aActor)
{
RefPtr<WebBrowserPersistResourcesChild> visitor =
static_cast<WebBrowserPersistResourcesChild*>(aActor);
nsresult rv = mDocument->ReadResources(visitor);
if (NS_FAILED(rv)) {
// This is a sync failure on the child side but an async
// failure on the parent side -- it already got NS_OK from
// ReadResources, so the error has to be reported via the
// visitor instead.
visitor->EndVisit(mDocument, rv);
}
return true;
}
bool
WebBrowserPersistDocumentChild::DeallocPWebBrowserPersistResourcesChild(PWebBrowserPersistResourcesChild* aActor)
{
auto* castActor =
static_cast<WebBrowserPersistResourcesChild*>(aActor);
NS_RELEASE(castActor);
return true;
}
PWebBrowserPersistSerializeChild*
WebBrowserPersistDocumentChild::AllocPWebBrowserPersistSerializeChild(
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn)
{
auto* actor = new WebBrowserPersistSerializeChild(aMap);
NS_ADDREF(actor);
return actor;
}
bool
WebBrowserPersistDocumentChild::RecvPWebBrowserPersistSerializeConstructor(
PWebBrowserPersistSerializeChild* aActor,
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn)
{
auto* castActor =
static_cast<WebBrowserPersistSerializeChild*>(aActor);
// This actor performs the roles of: completion, URI map, and output stream.
nsresult rv = mDocument->WriteContent(castActor,
castActor,
aRequestedContentType,
aEncoderFlags,
aWrapColumn,
castActor);
if (NS_FAILED(rv)) {
castActor->OnFinish(mDocument, castActor, aRequestedContentType, rv);
}
return true;
}
bool
WebBrowserPersistDocumentChild::DeallocPWebBrowserPersistSerializeChild(PWebBrowserPersistSerializeChild* aActor)
{
auto* castActor =
static_cast<WebBrowserPersistSerializeChild*>(aActor);
NS_RELEASE(castActor);
return true;
}
} // namespace mozilla

View file

@ -0,0 +1,62 @@
/* -*- 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/. */
#ifndef WebBrowserPersistDocumentChild_h__
#define WebBrowserPersistDocumentChild_h__
#include "mozilla/PWebBrowserPersistDocumentChild.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
class nsIDocument;
namespace mozilla {
class WebBrowserPersistDocumentChild final
: public PWebBrowserPersistDocumentChild
{
public:
WebBrowserPersistDocumentChild();
~WebBrowserPersistDocumentChild();
// This sends either Attributes or InitFailure and thereby causes
// the actor to leave the START state.
void Start(nsIWebBrowserPersistDocument* aDocument);
void Start(nsIDocument* aDocument);
virtual bool
RecvSetPersistFlags(const uint32_t& aNewFlags) override;
virtual PWebBrowserPersistResourcesChild*
AllocPWebBrowserPersistResourcesChild() override;
virtual bool
RecvPWebBrowserPersistResourcesConstructor(PWebBrowserPersistResourcesChild* aActor) override;
virtual bool
DeallocPWebBrowserPersistResourcesChild(PWebBrowserPersistResourcesChild* aActor) override;
virtual PWebBrowserPersistSerializeChild*
AllocPWebBrowserPersistSerializeChild(
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn) override;
virtual bool
RecvPWebBrowserPersistSerializeConstructor(
PWebBrowserPersistSerializeChild* aActor,
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn) override;
virtual bool
DeallocPWebBrowserPersistSerializeChild(PWebBrowserPersistSerializeChild* aActor) override;
private:
nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
};
} // namespace mozilla
#endif // WebBrowserPersistDocumentChild_h__

View file

@ -0,0 +1,125 @@
/* -*- 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 "WebBrowserPersistDocumentParent.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsIInputStream.h"
#include "nsThreadUtils.h"
#include "WebBrowserPersistResourcesParent.h"
#include "WebBrowserPersistSerializeParent.h"
#include "WebBrowserPersistRemoteDocument.h"
namespace mozilla {
WebBrowserPersistDocumentParent::WebBrowserPersistDocumentParent()
: mReflection(nullptr)
{
}
void
WebBrowserPersistDocumentParent::SetOnReady(nsIWebBrowserPersistDocumentReceiver* aOnReady)
{
MOZ_ASSERT(aOnReady);
MOZ_ASSERT(!mOnReady);
MOZ_ASSERT(!mReflection);
mOnReady = aOnReady;
}
void
WebBrowserPersistDocumentParent::ActorDestroy(ActorDestroyReason aWhy)
{
if (mReflection) {
mReflection->ActorDestroy();
mReflection = nullptr;
}
if (mOnReady) {
// Bug 1202887: If this is part of a subtree destruction, then
// anything which could cause another actor in that subtree to
// be Send__delete__()ed will cause use-after-free -- such as
// dropping the last reference to another document's
// WebBrowserPersistRemoteDocument. To avoid that, defer the
// callback until after the entire subtree is destroyed.
nsCOMPtr<nsIRunnable> errorLater = NewRunnableMethod
<nsresult>(mOnReady, &nsIWebBrowserPersistDocumentReceiver::OnError,
NS_ERROR_FAILURE);
NS_DispatchToCurrentThread(errorLater);
mOnReady = nullptr;
}
}
WebBrowserPersistDocumentParent::~WebBrowserPersistDocumentParent()
{
MOZ_RELEASE_ASSERT(!mReflection);
MOZ_ASSERT(!mOnReady);
}
bool
WebBrowserPersistDocumentParent::RecvAttributes(const Attrs& aAttrs,
const OptionalInputStreamParams& aPostData,
nsTArray<FileDescriptor>&& aPostFiles)
{
// Deserialize the postData unconditionally so that fds aren't leaked.
nsCOMPtr<nsIInputStream> postData =
ipc::DeserializeInputStream(aPostData, aPostFiles);
if (!mOnReady || mReflection) {
return false;
}
mReflection = new WebBrowserPersistRemoteDocument(this, aAttrs, postData);
RefPtr<WebBrowserPersistRemoteDocument> reflection = mReflection;
mOnReady->OnDocumentReady(reflection);
mOnReady = nullptr;
return true;
}
bool
WebBrowserPersistDocumentParent::RecvInitFailure(const nsresult& aFailure)
{
if (!mOnReady || mReflection) {
return false;
}
mOnReady->OnError(aFailure);
mOnReady = nullptr;
// Warning: Send__delete__ deallocates this object.
return Send__delete__(this);
}
PWebBrowserPersistResourcesParent*
WebBrowserPersistDocumentParent::AllocPWebBrowserPersistResourcesParent()
{
MOZ_CRASH("Don't use this; construct the actor directly and AddRef.");
return nullptr;
}
bool
WebBrowserPersistDocumentParent::DeallocPWebBrowserPersistResourcesParent(PWebBrowserPersistResourcesParent* aActor)
{
// Turn the ref held by IPC back into an nsRefPtr.
RefPtr<WebBrowserPersistResourcesParent> actor =
already_AddRefed<WebBrowserPersistResourcesParent>(
static_cast<WebBrowserPersistResourcesParent*>(aActor));
return true;
}
PWebBrowserPersistSerializeParent*
WebBrowserPersistDocumentParent::AllocPWebBrowserPersistSerializeParent(
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn)
{
MOZ_CRASH("Don't use this; construct the actor directly.");
return nullptr;
}
bool
WebBrowserPersistDocumentParent::DeallocPWebBrowserPersistSerializeParent(PWebBrowserPersistSerializeParent* aActor)
{
delete aActor;
return true;
}
} // namespace mozilla

View file

@ -0,0 +1,79 @@
/* -*- 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/. */
#ifndef WebBrowserPersistDocumentParent_h__
#define WebBrowserPersistDocumentParent_h__
#include "mozilla/Maybe.h"
#include "mozilla/PWebBrowserPersistDocumentParent.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
// This class is the IPC half of the glue between the
// nsIWebBrowserPersistDocument interface and a remote document. When
// (and if) it receives the Attributes message it constructs an
// WebBrowserPersistRemoteDocument and releases it into the XPCOM
// universe; otherwise, it invokes the document receiver's error
// callback.
//
// This object's lifetime is the normal IPC lifetime; on destruction,
// it calls its XPCOM reflection (if it exists yet) to remove that
// reference. Normal deletion occurs when the XPCOM object is being
// destroyed or after an InitFailure is received and handled.
//
// See also: TabParent::StartPersistence.
namespace mozilla {
class WebBrowserPersistRemoteDocument;
class WebBrowserPersistDocumentParent final
: public PWebBrowserPersistDocumentParent
{
public:
WebBrowserPersistDocumentParent();
virtual ~WebBrowserPersistDocumentParent();
// Set a callback to be invoked when the actor leaves the START
// state. This method must be called exactly once while the actor
// is still in the START state (or is unconstructed).
void SetOnReady(nsIWebBrowserPersistDocumentReceiver* aOnReady);
using Attrs = WebBrowserPersistDocumentAttrs;
// IPDL methods:
virtual bool
RecvAttributes(const Attrs& aAttrs,
const OptionalInputStreamParams& aPostData,
nsTArray<FileDescriptor>&& aPostFiles) override;
virtual bool
RecvInitFailure(const nsresult& aFailure) override;
virtual PWebBrowserPersistResourcesParent*
AllocPWebBrowserPersistResourcesParent() override;
virtual bool
DeallocPWebBrowserPersistResourcesParent(PWebBrowserPersistResourcesParent* aActor) override;
virtual PWebBrowserPersistSerializeParent*
AllocPWebBrowserPersistSerializeParent(
const WebBrowserPersistURIMap& aMap,
const nsCString& aRequestedContentType,
const uint32_t& aEncoderFlags,
const uint32_t& aWrapColumn) override;
virtual bool
DeallocPWebBrowserPersistSerializeParent(PWebBrowserPersistSerializeParent* aActor) override;
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
private:
// This is reset to nullptr when the callback is invoked.
nsCOMPtr<nsIWebBrowserPersistDocumentReceiver> mOnReady;
WebBrowserPersistRemoteDocument* mReflection;
};
} // namespace mozilla
#endif // WebBrowserPersistDocumentParent_h__

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
/* -*- 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/. */
#ifndef WebBrowserPersistLocalDocument_h__
#define WebBrowserPersistLocalDocument_h__
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDocument.h"
#include "nsIURI.h"
#include "nsIWebBrowserPersistDocument.h"
class nsIDocumentEncoder;
class nsISHEntry;
namespace mozilla {
class WebBrowserPersistLocalDocument final
: public nsIWebBrowserPersistDocument
{
public:
explicit WebBrowserPersistLocalDocument(nsIDocument* aDocument);
const nsCString& GetCharacterSet() const;
uint32_t GetPersistFlags() const;
already_AddRefed<nsIURI> GetBaseURI() const;
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIWEBBROWSERPERSISTDOCUMENT
NS_DECL_CYCLE_COLLECTION_CLASS(WebBrowserPersistLocalDocument)
private:
nsCOMPtr<nsIDocument> mDocument;
uint32_t mPersistFlags;
void DecideContentType(nsACString& aContentType);
nsresult GetDocEncoder(const nsACString& aContentType,
uint32_t aEncoderFlags,
nsIDocumentEncoder** aEncoder);
already_AddRefed<nsISHEntry> GetHistory();
virtual ~WebBrowserPersistLocalDocument();
};
} // namespace mozilla
#endif // WebBrowserPersistLocalDocument_h__

View file

@ -0,0 +1,186 @@
/* -*- 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 "WebBrowserPersistRemoteDocument.h"
#include "WebBrowserPersistDocumentParent.h"
#include "WebBrowserPersistResourcesParent.h"
#include "WebBrowserPersistSerializeParent.h"
#include "mozilla/Unused.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(WebBrowserPersistRemoteDocument,
nsIWebBrowserPersistDocument)
WebBrowserPersistRemoteDocument
::WebBrowserPersistRemoteDocument(WebBrowserPersistDocumentParent* aActor,
const Attrs& aAttrs,
nsIInputStream* aPostData)
: mActor(aActor)
, mAttrs(aAttrs)
, mPostData(aPostData)
{
}
WebBrowserPersistRemoteDocument::~WebBrowserPersistRemoteDocument()
{
if (mActor) {
Unused << mActor->Send__delete__(mActor);
// That will call mActor->ActorDestroy, which calls this->ActorDestroy
// (whether or not the IPC send succeeds).
}
MOZ_ASSERT(!mActor);
}
void
WebBrowserPersistRemoteDocument::ActorDestroy(void)
{
mActor = nullptr;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetIsPrivate(bool* aIsPrivate)
{
*aIsPrivate = mAttrs.isPrivate();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetDocumentURI(nsACString& aURISpec)
{
aURISpec = mAttrs.documentURI();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetBaseURI(nsACString& aURISpec)
{
aURISpec = mAttrs.baseURI();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetContentType(nsACString& aContentType)
{
aContentType = mAttrs.contentType();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetCharacterSet(nsACString& aCharSet)
{
aCharSet = mAttrs.characterSet();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetTitle(nsAString& aTitle)
{
aTitle = mAttrs.title();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetReferrer(nsAString& aReferrer)
{
aReferrer = mAttrs.referrer();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetContentDisposition(nsAString& aDisp)
{
aDisp = mAttrs.contentDisposition();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetCacheKey(uint32_t* aCacheKey)
{
*aCacheKey = mAttrs.cacheKey();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetPersistFlags(uint32_t* aFlags)
{
*aFlags = mAttrs.persistFlags();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::SetPersistFlags(uint32_t aFlags)
{
if (!mActor) {
return NS_ERROR_FAILURE;
}
if (!mActor->SendSetPersistFlags(aFlags)) {
return NS_ERROR_FAILURE;
}
mAttrs.persistFlags() = aFlags;
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetPostData(nsIInputStream** aStream)
{
nsCOMPtr<nsIInputStream> stream = mPostData;
stream.forget(aStream);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::ReadResources(nsIWebBrowserPersistResourceVisitor* aVisitor)
{
if (!mActor) {
return NS_ERROR_FAILURE;
}
RefPtr<WebBrowserPersistResourcesParent> subActor =
new WebBrowserPersistResourcesParent(this, aVisitor);
return mActor->SendPWebBrowserPersistResourcesConstructor(
subActor.forget().take())
? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
WebBrowserPersistRemoteDocument::WriteContent(
nsIOutputStream* aStream,
nsIWebBrowserPersistURIMap* aMap,
const nsACString& aRequestedContentType,
uint32_t aEncoderFlags,
uint32_t aWrapColumn,
nsIWebBrowserPersistWriteCompletion* aCompletion)
{
if (!mActor) {
return NS_ERROR_FAILURE;
}
nsresult rv;
WebBrowserPersistURIMap map;
uint32_t numMappedURIs;
if (aMap) {
rv = aMap->GetTargetBaseURI(map.targetBaseURI());
NS_ENSURE_SUCCESS(rv, rv);
rv = aMap->GetNumMappedURIs(&numMappedURIs);
NS_ENSURE_SUCCESS(rv, rv);
for (uint32_t i = 0; i < numMappedURIs; ++i) {
WebBrowserPersistURIMapEntry& nextEntry =
*(map.mapURIs().AppendElement());
rv = aMap->GetURIMapping(i, nextEntry.mapFrom(), nextEntry.mapTo());
NS_ENSURE_SUCCESS(rv, rv);
}
}
auto* subActor = new WebBrowserPersistSerializeParent(this,
aStream,
aCompletion);
nsCString requestedContentType(aRequestedContentType); // Sigh.
return mActor->SendPWebBrowserPersistSerializeConstructor(
subActor, map, requestedContentType, aEncoderFlags, aWrapColumn)
? NS_OK : NS_ERROR_FAILURE;
}
} // namespace mozilla

View file

@ -0,0 +1,55 @@
/* -*- 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/. */
#ifndef WebBrowserPersistRemoteDocument_h__
#define WebBrowserPersistRemoteDocument_h__
#include "mozilla/Maybe.h"
#include "mozilla/PWebBrowserPersistDocumentParent.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
#include "nsIInputStream.h"
// This class is the XPCOM half of the glue between the
// nsIWebBrowserPersistDocument interface and a remote document; it is
// created by WebBrowserPersistDocumentParent when (and if) it
// receives the information needed to populate the interface's
// properties.
//
// This object has a normal refcounted lifetime. The corresponding
// IPC actor holds a weak reference to this class; when the last
// strong reference is released, it sends an IPC delete message and
// thereby removes that reference.
namespace mozilla {
class WebBrowserPersistDocumentParent;
class WebBrowserPersistRemoteDocument final
: public nsIWebBrowserPersistDocument
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBBROWSERPERSISTDOCUMENT
private:
using Attrs = WebBrowserPersistDocumentAttrs;
WebBrowserPersistDocumentParent* mActor;
Attrs mAttrs;
nsCOMPtr<nsIInputStream> mPostData;
friend class WebBrowserPersistDocumentParent;
WebBrowserPersistRemoteDocument(WebBrowserPersistDocumentParent* aActor,
const Attrs& aAttrs,
nsIInputStream* aPostData);
~WebBrowserPersistRemoteDocument();
void ActorDestroy(void);
};
} // namespace mozilla
#endif // WebBrowserPersistRemoteDocument_h__

View file

@ -0,0 +1,73 @@
/* -*- 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 "WebBrowserPersistResourcesChild.h"
#include "WebBrowserPersistDocumentChild.h"
#include "mozilla/dom/ContentChild.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(WebBrowserPersistResourcesChild,
nsIWebBrowserPersistResourceVisitor)
WebBrowserPersistResourcesChild::WebBrowserPersistResourcesChild()
{
}
WebBrowserPersistResourcesChild::~WebBrowserPersistResourcesChild()
{
}
NS_IMETHODIMP
WebBrowserPersistResourcesChild::VisitResource(nsIWebBrowserPersistDocument *aDocument,
const nsACString& aURI)
{
nsCString copiedURI(aURI); // Yay, XPIDL/IPDL mismatch.
SendVisitResource(copiedURI);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistResourcesChild::VisitDocument(nsIWebBrowserPersistDocument* aDocument,
nsIWebBrowserPersistDocument* aSubDocument)
{
auto* subActor = new WebBrowserPersistDocumentChild();
// As a consequence of how PWebBrowserPersistDocumentConstructor
// can be sent by both the parent and the child, we must pass the
// aBrowser and outerWindowID arguments here, but the values are
// ignored by the parent. In particular, the TabChild in which
// persistence started does not necessarily exist at this point;
// see bug 1203602.
if (!Manager()->Manager()
->SendPWebBrowserPersistDocumentConstructor(subActor, nullptr, 0)) {
// NOTE: subActor is freed at this point.
return NS_ERROR_FAILURE;
}
// ...but here, IPC won't free subActor until after this returns
// to the event loop.
// The order of these two messages will be preserved, because
// they're the same toplevel protocol and priority.
//
// With this ordering, it's always the transition out of START
// state that causes a document's parent actor to be exposed to
// XPCOM (for both parent->child and child->parent construction),
// which simplifies the lifetime management.
SendVisitDocument(subActor);
subActor->Start(aSubDocument);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistResourcesChild::EndVisit(nsIWebBrowserPersistDocument *aDocument,
nsresult aStatus)
{
Send__delete__(this, aStatus);
return NS_OK;
}
} // namespace mozilla

View file

@ -0,0 +1,31 @@
/* -*- 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/. */
#ifndef WebBrowserPersistResourcesChild_h__
#define WebBrowserPersistResourcesChild_h__
#include "mozilla/PWebBrowserPersistResourcesChild.h"
#include "nsIWebBrowserPersistDocument.h"
namespace mozilla {
class WebBrowserPersistResourcesChild final
: public PWebBrowserPersistResourcesChild
, public nsIWebBrowserPersistResourceVisitor
{
public:
WebBrowserPersistResourcesChild();
NS_DECL_NSIWEBBROWSERPERSISTRESOURCEVISITOR
NS_DECL_ISUPPORTS
private:
virtual ~WebBrowserPersistResourcesChild();
};
} // namespace mozilla
#endif // WebBrowserPersistDocumentChild_h__

View file

@ -0,0 +1,87 @@
/* -*- 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 "WebBrowserPersistResourcesParent.h"
#include "nsThreadUtils.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(WebBrowserPersistResourcesParent,
nsIWebBrowserPersistDocumentReceiver)
WebBrowserPersistResourcesParent::WebBrowserPersistResourcesParent(
nsIWebBrowserPersistDocument* aDocument,
nsIWebBrowserPersistResourceVisitor* aVisitor)
: mDocument(aDocument)
, mVisitor(aVisitor)
{
MOZ_ASSERT(aDocument);
MOZ_ASSERT(aVisitor);
}
WebBrowserPersistResourcesParent::~WebBrowserPersistResourcesParent()
{
}
void
WebBrowserPersistResourcesParent::ActorDestroy(ActorDestroyReason aWhy)
{
if (aWhy != Deletion && mVisitor) {
// See comment in WebBrowserPersistDocumentParent::ActorDestroy
// (or bug 1202887) for why this is deferred.
nsCOMPtr<nsIRunnable> errorLater = NewRunnableMethod
<nsCOMPtr<nsIWebBrowserPersistDocument>, nsresult>
(mVisitor, &nsIWebBrowserPersistResourceVisitor::EndVisit,
mDocument, NS_ERROR_FAILURE);
NS_DispatchToCurrentThread(errorLater);
}
mVisitor = nullptr;
}
bool
WebBrowserPersistResourcesParent::Recv__delete__(const nsresult& aStatus)
{
mVisitor->EndVisit(mDocument, aStatus);
mVisitor = nullptr;
return true;
}
bool
WebBrowserPersistResourcesParent::RecvVisitResource(const nsCString& aURI)
{
mVisitor->VisitResource(mDocument, aURI);
return true;
}
bool
WebBrowserPersistResourcesParent::RecvVisitDocument(PWebBrowserPersistDocumentParent* aSubDocument)
{
// Don't expose the subdocument to the visitor until it's ready
// (until the actor isn't in START state).
static_cast<WebBrowserPersistDocumentParent*>(aSubDocument)
->SetOnReady(this);
return true;
}
NS_IMETHODIMP
WebBrowserPersistResourcesParent::OnDocumentReady(nsIWebBrowserPersistDocument* aSubDocument)
{
if (!mVisitor) {
return NS_ERROR_FAILURE;
}
mVisitor->VisitDocument(mDocument, aSubDocument);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistResourcesParent::OnError(nsresult aFailure)
{
// Nothing useful to do but ignore the failed document.
return NS_OK;
}
} // namespace mozilla

View file

@ -0,0 +1,54 @@
/* -*- 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/. */
#ifndef WebBrowserPersistResourcesParent_h__
#define WebBrowserPersistResourcesParent_h__
#include "mozilla/PWebBrowserPersistResourcesParent.h"
#include "WebBrowserPersistDocumentParent.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
namespace mozilla {
class WebBrowserPersistResourcesParent final
: public PWebBrowserPersistResourcesParent
, public nsIWebBrowserPersistDocumentReceiver
{
public:
WebBrowserPersistResourcesParent(nsIWebBrowserPersistDocument* aDocument,
nsIWebBrowserPersistResourceVisitor* aVisitor);
virtual bool
RecvVisitResource(const nsCString& aURI) override;
virtual bool
RecvVisitDocument(PWebBrowserPersistDocumentParent* aSubDocument) override;
virtual bool
Recv__delete__(const nsresult& aStatus) override;
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
NS_DECL_NSIWEBBROWSERPERSISTDOCUMENTRECEIVER
NS_DECL_ISUPPORTS
private:
// Note: even if the XPIDL didn't need mDocument for visitor
// callbacks, this object still needs to hold a strong reference
// to it to defer actor subtree deletion until after the
// visitation is finished.
nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
nsCOMPtr<nsIWebBrowserPersistResourceVisitor> mVisitor;
virtual ~WebBrowserPersistResourcesParent();
};
} // namespace mozilla
#endif // WebBrowserPersistResourcesParent_h__

View file

@ -0,0 +1,143 @@
/* -*- 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 "WebBrowserPersistSerializeChild.h"
#include <algorithm>
#include "nsThreadUtils.h"
#include "ipc/IPCMessageUtils.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(WebBrowserPersistSerializeChild,
nsIWebBrowserPersistWriteCompletion,
nsIWebBrowserPersistURIMap,
nsIOutputStream)
WebBrowserPersistSerializeChild::WebBrowserPersistSerializeChild(const WebBrowserPersistURIMap& aMap)
: mMap(aMap)
{
}
WebBrowserPersistSerializeChild::~WebBrowserPersistSerializeChild()
{
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::OnFinish(nsIWebBrowserPersistDocument* aDocument,
nsIOutputStream* aStream,
const nsACString& aContentType,
nsresult aStatus)
{
MOZ_ASSERT(aStream == this);
nsCString contentType(aContentType);
Send__delete__(this, contentType, aStatus);
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::GetNumMappedURIs(uint32_t* aNum)
{
*aNum = static_cast<uint32_t>(mMap.mapURIs().Length());
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::GetURIMapping(uint32_t aIndex,
nsACString& aMapFrom,
nsACString& aMapTo)
{
if (aIndex >= mMap.mapURIs().Length()) {
return NS_ERROR_INVALID_ARG;
}
aMapFrom = mMap.mapURIs()[aIndex].mapFrom();
aMapTo = mMap.mapURIs()[aIndex].mapTo();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::GetTargetBaseURI(nsACString& aURI)
{
aURI = mMap.targetBaseURI();
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::Close()
{
NS_WARNING("WebBrowserPersistSerializeChild::Close()");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::Flush()
{
NS_WARNING("WebBrowserPersistSerializeChild::Flush()");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::Write(const char* aBuf, uint32_t aCount,
uint32_t* aWritten)
{
// Normally an nsIOutputStream would have to be thread-safe, but
// nsDocumentEncoder currently doesn't call this off the main
// thread (which also means it's difficult to test the
// thread-safety code this class doesn't yet have).
//
// This is *not* an NS_ERROR_NOT_IMPLEMENTED, because at this
// point we've probably already misused the non-thread-safe
// refcounting.
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Fix this class to be thread-safe.");
// Work around bug 1181433 by sending multiple messages if
// necessary to write the entire aCount bytes, even though
// nsIOutputStream.idl says we're allowed to do a short write.
const char* buf = aBuf;
uint32_t count = aCount;
*aWritten = 0;
while (count > 0) {
uint32_t toWrite = std::min(IPC::MAX_MESSAGE_SIZE, count);
nsTArray<uint8_t> arrayBuf;
// It would be nice if this extra copy could be avoided.
arrayBuf.AppendElements(buf, toWrite);
SendWriteData(Move(arrayBuf));
*aWritten += toWrite;
buf += toWrite;
count -= toWrite;
}
return NS_OK;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::WriteFrom(nsIInputStream* aFrom,
uint32_t aCount,
uint32_t* aWritten)
{
NS_WARNING("WebBrowserPersistSerializeChild::WriteFrom()");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::WriteSegments(nsReadSegmentFun aFun,
void* aCtx,
uint32_t aCount,
uint32_t* aWritten)
{
NS_WARNING("WebBrowserPersistSerializeChild::WriteSegments()");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
WebBrowserPersistSerializeChild::IsNonBlocking(bool* aNonBlocking)
{
// Writes will never fail with NS_BASE_STREAM_WOULD_BLOCK, so:
*aNonBlocking = false;
return NS_OK;
}
} // namespace mozilla

View file

@ -0,0 +1,39 @@
/* -*- 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/. */
#ifndef WebBrowserPersistSerializeChild_h__
#define WebBrowserPersistSerializeChild_h__
#include "mozilla/PWebBrowserPersistSerializeChild.h"
#include "mozilla/PWebBrowserPersistDocument.h"
#include "nsIWebBrowserPersistDocument.h"
#include "nsIOutputStream.h"
namespace mozilla {
class WebBrowserPersistSerializeChild final
: public PWebBrowserPersistSerializeChild
, public nsIWebBrowserPersistWriteCompletion
, public nsIWebBrowserPersistURIMap
, public nsIOutputStream
{
public:
explicit WebBrowserPersistSerializeChild(const WebBrowserPersistURIMap& aMap);
NS_DECL_NSIWEBBROWSERPERSISTWRITECOMPLETION
NS_DECL_NSIWEBBROWSERPERSISTURIMAP
NS_DECL_NSIOUTPUTSTREAM
NS_DECL_ISUPPORTS
private:
WebBrowserPersistURIMap mMap;
virtual ~WebBrowserPersistSerializeChild();
};
} // namespace mozilla
#endif // WebBrowserPersistSerializeChild_h__

View file

@ -0,0 +1,90 @@
/* -*- 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 "WebBrowserPersistSerializeParent.h"
#include "nsReadableUtils.h"
#include "nsThreadUtils.h"
namespace mozilla {
WebBrowserPersistSerializeParent::WebBrowserPersistSerializeParent(
nsIWebBrowserPersistDocument* aDocument,
nsIOutputStream* aStream,
nsIWebBrowserPersistWriteCompletion* aFinish)
: mDocument(aDocument)
, mStream(aStream)
, mFinish(aFinish)
, mOutputError(NS_OK)
{
MOZ_ASSERT(aDocument);
MOZ_ASSERT(aStream);
MOZ_ASSERT(aFinish);
}
WebBrowserPersistSerializeParent::~WebBrowserPersistSerializeParent()
{
}
bool
WebBrowserPersistSerializeParent::RecvWriteData(nsTArray<uint8_t>&& aData)
{
if (NS_FAILED(mOutputError)) {
return true;
}
uint32_t written = 0;
static_assert(sizeof(char) == sizeof(uint8_t),
"char must be (at least?) 8 bits");
const char* data = reinterpret_cast<const char*>(aData.Elements());
// nsIOutputStream::Write is allowed to return short writes.
while (written < aData.Length()) {
uint32_t writeReturn;
nsresult rv = mStream->Write(data + written,
aData.Length() - written,
&writeReturn);
if (NS_FAILED(rv)) {
mOutputError = rv;
return true;
}
written += writeReturn;
}
return true;
}
bool
WebBrowserPersistSerializeParent::Recv__delete__(const nsCString& aContentType,
const nsresult& aStatus)
{
if (NS_SUCCEEDED(mOutputError)) {
mOutputError = aStatus;
}
mFinish->OnFinish(mDocument,
mStream,
aContentType,
mOutputError);
mFinish = nullptr;
return true;
}
void
WebBrowserPersistSerializeParent::ActorDestroy(ActorDestroyReason aWhy)
{
if (mFinish) {
MOZ_ASSERT(aWhy != Deletion);
// See comment in WebBrowserPersistDocumentParent::ActorDestroy
// (or bug 1202887) for why this is deferred.
nsCOMPtr<nsIRunnable> errorLater = NewRunnableMethod
<nsCOMPtr<nsIWebBrowserPersistDocument>, nsCOMPtr<nsIOutputStream>,
nsCString, nsresult>
(mFinish, &nsIWebBrowserPersistWriteCompletion::OnFinish,
mDocument, mStream, EmptyCString(), NS_ERROR_FAILURE);
NS_DispatchToCurrentThread(errorLater);
mFinish = nullptr;
}
}
} // namespace mozilla

View file

@ -0,0 +1,49 @@
/* -*- 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/. */
#ifndef WebBrowserPersistSerializeParent_h__
#define WebBrowserPersistSerializeParent_h__
#include "mozilla/PWebBrowserPersistSerializeParent.h"
#include "nsCOMPtr.h"
#include "nsIOutputStream.h"
#include "nsIWebBrowserPersistDocument.h"
namespace mozilla {
class WebBrowserPersistSerializeParent
: public PWebBrowserPersistSerializeParent
{
public:
WebBrowserPersistSerializeParent(
nsIWebBrowserPersistDocument* aDocument,
nsIOutputStream* aStream,
nsIWebBrowserPersistWriteCompletion* aFinish);
virtual ~WebBrowserPersistSerializeParent();
virtual bool
RecvWriteData(nsTArray<uint8_t>&& aData) override;
virtual bool
Recv__delete__(const nsCString& aContentType,
const nsresult& aStatus) override;
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
private:
// See also ...ReadParent::mDocument for the other reason this
// strong reference needs to be here.
nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
nsCOMPtr<nsIOutputStream> mStream;
nsCOMPtr<nsIWebBrowserPersistWriteCompletion> mFinish;
nsresult mOutputError;
};
} // namespace mozilla
#endif // WebBrowserPersistSerializeParent_h__

View file

@ -0,0 +1,49 @@
# -*- 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/.
XPIDL_SOURCES += [
'nsCWebBrowserPersist.idl',
'nsIWebBrowserPersist.idl',
'nsIWebBrowserPersistable.idl',
'nsIWebBrowserPersistDocument.idl',
]
XPIDL_MODULE = 'webbrowserpersist'
IPDL_SOURCES += [
'PWebBrowserPersistDocument.ipdl',
'PWebBrowserPersistResources.ipdl',
'PWebBrowserPersistSerialize.ipdl',
]
SOURCES += [
'nsWebBrowserPersist.cpp',
'WebBrowserPersistDocumentChild.cpp',
'WebBrowserPersistDocumentParent.cpp',
'WebBrowserPersistLocalDocument.cpp',
'WebBrowserPersistRemoteDocument.cpp',
'WebBrowserPersistResourcesChild.cpp',
'WebBrowserPersistResourcesParent.cpp',
'WebBrowserPersistSerializeChild.cpp',
'WebBrowserPersistSerializeParent.cpp',
]
EXPORTS.mozilla += [
'WebBrowserPersistDocumentChild.h',
'WebBrowserPersistDocumentParent.h',
'WebBrowserPersistLocalDocument.h',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/dom/base',
'/dom/html',
]
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']

View file

@ -0,0 +1,15 @@
/* -*- 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 "nsIWebBrowserPersist.idl"
%{ C++
// {7E677795-C582-4cd1-9E8D-8271B3474D2A}
#define NS_WEBBROWSERPERSIST_CID \
{ 0x7e677795, 0xc582, 0x4cd1, { 0x9e, 0x8d, 0x82, 0x71, 0xb3, 0x47, 0x4d, 0x2a } }
#define NS_WEBBROWSERPERSIST_CONTRACTID \
"@mozilla.org/embedding/browser/nsWebBrowserPersist;1"
%}

View file

@ -0,0 +1,286 @@
/* -*- 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 "nsICancelable.idl"
interface nsIURI;
interface nsIInputStream;
interface nsIDOMDocument;
interface nsIWebProgressListener;
interface nsIFile;
interface nsIChannel;
interface nsILoadContext;
/**
* Interface for persisting DOM documents and URIs to local or remote storage.
*/
[scriptable, uuid(8cd752a4-60b1-42c3-a819-65c7a1138a28)]
interface nsIWebBrowserPersist : nsICancelable
{
/** No special persistence behaviour. */
const unsigned long PERSIST_FLAGS_NONE = 0;
/** Use cached data if present (skipping validation), else load from network */
const unsigned long PERSIST_FLAGS_FROM_CACHE = 1;
/** Bypass the cached data. */
const unsigned long PERSIST_FLAGS_BYPASS_CACHE = 2;
/** Ignore any redirected data (usually adverts). */
const unsigned long PERSIST_FLAGS_IGNORE_REDIRECTED_DATA = 4;
/** Ignore IFRAME content (usually adverts). */
const unsigned long PERSIST_FLAGS_IGNORE_IFRAMES = 8;
/** Do not run the incoming data through a content converter e.g. to decompress it */
const unsigned long PERSIST_FLAGS_NO_CONVERSION = 16;
/** Replace existing files on the disk (use with due diligence!) */
const unsigned long PERSIST_FLAGS_REPLACE_EXISTING_FILES = 32;
/** Don't modify or add base tags */
const unsigned long PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS = 64;
/** Make changes to original dom rather than cloning nodes */
const unsigned long PERSIST_FLAGS_FIXUP_ORIGINAL_DOM = 128;
/** Fix links relative to destination location (not origin) */
const unsigned long PERSIST_FLAGS_FIXUP_LINKS_TO_DESTINATION = 256;
/** Don't make any adjustments to links */
const unsigned long PERSIST_FLAGS_DONT_FIXUP_LINKS = 512;
/** Force serialization of output (one file at a time; not concurrent) */
const unsigned long PERSIST_FLAGS_SERIALIZE_OUTPUT = 1024;
/** Don't make any adjustments to filenames */
const unsigned long PERSIST_FLAGS_DONT_CHANGE_FILENAMES = 2048;
/** Fail on broken inline links */
const unsigned long PERSIST_FLAGS_FAIL_ON_BROKEN_LINKS = 4096;
/**
* Automatically cleanup after a failed or cancelled operation, deleting all
* created files and directories. This flag does nothing for failed upload
* operations to remote servers.
*/
const unsigned long PERSIST_FLAGS_CLEANUP_ON_FAILURE = 8192;
/**
* Let the WebBrowserPersist decide whether the incoming data is encoded
* and whether it needs to go through a content converter e.g. to
* decompress it.
*/
const unsigned long PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION = 16384;
/**
* Append the downloaded data to the target file.
* This can only be used when persisting to a local file.
*/
const unsigned long PERSIST_FLAGS_APPEND_TO_FILE = 32768;
/**
* Force relevant cookies to be sent with this load even if normally they
* wouldn't be.
*/
const unsigned long PERSIST_FLAGS_FORCE_ALLOW_COOKIES = 65536;
/**
* Flags governing how data is fetched and saved from the network.
* It is best to set this value explicitly unless you are prepared
* to accept the default values.
*/
attribute unsigned long persistFlags;
/** Persister is ready to save data */
const unsigned long PERSIST_STATE_READY = 1;
/** Persister is saving data */
const unsigned long PERSIST_STATE_SAVING = 2;
/** Persister has finished saving data */
const unsigned long PERSIST_STATE_FINISHED = 3;
/**
* Current state of the persister object.
*/
readonly attribute unsigned long currentState;
/**
* Value indicating the success or failure of the persist
* operation.
*
* @throws NS_BINDING_ABORTED Operation cancelled.
* @throws NS_ERROR_FAILURE Non-specific failure.
*/
readonly attribute nsresult result;
/**
* Callback listener for progress notifications. The object that the
* embbedder supplies may also implement nsIInterfaceRequestor and be
* prepared to return nsIAuthPrompt or other interfaces that may be required
* to download data.
*
* @see nsIAuthPrompt
* @see nsIInterfaceRequestor
*/
attribute nsIWebProgressListener progressListener;
/**
* Save the specified URI to file.
*
* @param aURI URI to save to file. Some implementations of this interface
* may also support <CODE>nullptr</CODE> to imply the currently
* loaded URI.
* @param aCacheKey An object representing the URI in the cache or
* <CODE>nullptr</CODE>. This can be a necko cache key,
* an nsIWebPageDescriptor, or the currentDescriptor of an
* nsIWebPageDescriptor.
* @param aReferrer The referrer URI to pass with an HTTP request or
* <CODE>nullptr</CODE>.
* @param aReferrerPolicy The referrer policy for when and what to send via
* HTTP Referer header. Ignored if aReferrer is
* <CODE>nullptr</CODE>. Taken from REFERRER_POLICY
* constants in nsIHttpChannel.
* @param aPostData Post data to pass with an HTTP request or
* <CODE>nullptr</CODE>.
* @param aExtraHeaders Additional headers to supply with an HTTP request
* or <CODE>nullptr</CODE>.
* @param aFile Target file. This may be a nsIFile object or an
* nsIURI object with a file scheme or a scheme that
* supports uploading (e.g. ftp).
* @param aPrivacyContext A context from which the privacy status of this
* save operation can be determined. Must only be null
* in situations in which no such context is available
* (eg. the operation has no logical association with any
* window or document)
*
* @see nsIFile
* @see nsIURI
* @see nsIInputStream
*
* @throws NS_ERROR_INVALID_ARG One or more arguments was invalid.
*/
void saveURI(in nsIURI aURI, in nsISupports aCacheKey,
in nsIURI aReferrer, in unsigned long aReferrerPolicy,
in nsIInputStream aPostData,
in string aExtraHeaders, in nsISupports aFile,
in nsILoadContext aPrivacyContext);
/**
* @param aIsPrivate Treat the save operation as private (ie. with
* regards to networking operations and persistence
* of intermediate data, etc.)
* @see saveURI for all other parameter descriptions
*/
void savePrivacyAwareURI(in nsIURI aURI, in nsISupports aCacheKey,
in nsIURI aReferrer, in unsigned long aReferrerPolicy,
in nsIInputStream aPostData,
in string aExtraHeaders, in nsISupports aFile,
in boolean aIsPrivate);
/**
* Save a channel to a file. It must not be opened yet.
* @see saveURI
*/
void saveChannel(in nsIChannel aChannel, in nsISupports aFile);
/** Output only the current selection as opposed to the whole document. */
const unsigned long ENCODE_FLAGS_SELECTION_ONLY = 1;
/**
* For plaintext output. Convert html to plaintext that looks like the html.
* Implies wrap (except inside &lt;pre&gt;), since html wraps.
* HTML output: always do prettyprinting, ignoring existing formatting.
*/
const unsigned long ENCODE_FLAGS_FORMATTED = 2;
/**
* Output without formatting or wrapping the content. This flag
* may be used to preserve the original formatting as much as possible.
*/
const unsigned long ENCODE_FLAGS_RAW = 4;
/** Output only the body section, no HTML tags. */
const unsigned long ENCODE_FLAGS_BODY_ONLY = 8;
/** Wrap even if when not doing formatted output (e.g. for text fields). */
const unsigned long ENCODE_FLAGS_PREFORMATTED = 16;
/** Wrap documents at the specified column. */
const unsigned long ENCODE_FLAGS_WRAP = 32;
/**
* For plaintext output. Output for format flowed (RFC 2646). This is used
* when converting to text for mail sending. This differs just slightly
* but in an important way from normal formatted, and that is that
* lines are space stuffed. This can't (correctly) be done later.
*/
const unsigned long ENCODE_FLAGS_FORMAT_FLOWED = 64;
/** Convert links to absolute links where possible. */
const unsigned long ENCODE_FLAGS_ABSOLUTE_LINKS = 128;
/**
* Attempt to encode entities standardized at W3C (HTML, MathML, etc).
* This is a catch-all flag for documents with mixed contents. Beware of
* interoperability issues. See below for other flags which might likely
* do what you want.
*/
const unsigned long ENCODE_FLAGS_ENCODE_W3C_ENTITIES = 256;
/**
* Output with carriage return line breaks. May also be combined with
* ENCODE_FLAGS_LF_LINEBREAKS and if neither is specified, the platform
* default format is used.
*/
const unsigned long ENCODE_FLAGS_CR_LINEBREAKS = 512;
/**
* Output with linefeed line breaks. May also be combined with
* ENCODE_FLAGS_CR_LINEBREAKS and if neither is specified, the platform
* default format is used.
*/
const unsigned long ENCODE_FLAGS_LF_LINEBREAKS = 1024;
/** For plaintext output. Output the content of noscript elements. */
const unsigned long ENCODE_FLAGS_NOSCRIPT_CONTENT = 2048;
/** For plaintext output. Output the content of noframes elements. */
const unsigned long ENCODE_FLAGS_NOFRAMES_CONTENT = 4096;
/**
* Encode basic entities, e.g. output &nbsp; instead of character code 0xa0.
* The basic set is just &nbsp; &amp; &lt; &gt; &quot; for interoperability
* with older products that don't support &alpha; and friends.
*/
const unsigned long ENCODE_FLAGS_ENCODE_BASIC_ENTITIES = 8192;
/**
* Encode Latin1 entities. This includes the basic set and
* accented letters between 128 and 255.
*/
const unsigned long ENCODE_FLAGS_ENCODE_LATIN1_ENTITIES = 16384;
/**
* Encode HTML4 entities. This includes the basic set, accented
* letters, greek letters and certain special markup symbols.
*/
const unsigned long ENCODE_FLAGS_ENCODE_HTML_ENTITIES = 32768;
/**
* Save the specified DOM document to file and optionally all linked files
* (e.g. images, CSS, JS & subframes). Do not call this method until the
* document has finished loading!
*
* @param aDocument Document to save to file. Some implementations of
* this interface may also support <CODE>nullptr</CODE>
* to imply the currently loaded document. Can be an
* nsIWebBrowserPersistDocument or nsIDOMDocument.
* @param aFile Target local file. This may be a nsIFile object or an
* nsIURI object with a file scheme or a scheme that
* supports uploading (e.g. ftp).
* @param aDataPath Path to directory where URIs linked to the document
* are saved or nullptr if no linked URIs should be saved.
* This may be a nsIFile object or an nsIURI object
* with a file scheme.
* @param aOutputContentType The desired MIME type format to save the
* document and all subdocuments into or nullptr to use
* the default behaviour.
* @param aEncodingFlags Flags to pass to the encoder.
* @param aWrapColumn For text documents, indicates the desired width to
* wrap text at. Parameter is ignored if wrapping is not
* specified by the encoding flags.
*
* @see nsIWebBrowserPersistDocument
* @see nsIWebBrowserPersistable
* @see nsIFile
* @see nsIURI
*
* @throws NS_ERROR_INVALID_ARG One or more arguments was invalid.
*/
void saveDocument(in nsISupports aDocument,
in nsISupports aFile, in nsISupports aDataPath,
in string aOutputContentType, in unsigned long aEncodingFlags,
in unsigned long aWrapColumn);
/**
* Cancels the current operation. The caller is responsible for cleaning up
* partially written files or directories. This has the same effect as calling
* cancel with an argument of NS_BINDING_ABORTED.
*/
void cancelSave();
};

View file

@ -0,0 +1,197 @@
/* -*- Mode: IDL; 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 nsIDOMDocument;
interface nsIInputStream;
interface nsIOutputStream;
interface nsITabParent;
interface nsIWebBrowserPersistResourceVisitor;
interface nsIWebBrowserPersistWriteCompletion;
/**
* Interface for the URI-mapping information that can be supplied when
* serializing the DOM of an nsIWebBrowserPersistDocument.
*
* @see nsIWebBrowserPersistDocument
*/
[scriptable, uuid(d52e8b93-2771-45e8-a5b0-6e12b667046b)]
interface nsIWebBrowserPersistURIMap : nsISupports
{
/**
* The number of URI mappings.
*/
readonly attribute unsigned long numMappedURIs;
/**
* Obtain the URI mapping at the given index, which must be less than
* numMappedURIs, as a pair of URI spec strings.
*/
void getURIMapping(in unsigned long aIndex,
out AUTF8String aMapFrom,
out AUTF8String aMapTo);
/**
* The spec of the base URI that the document will have after it is
* serialized.
*/
readonly attribute AUTF8String targetBaseURI;
};
/**
* Interface representing a document that can be serialized with
* nsIWebBrowserPersist; it may or may not be in this process. Some
* information is exposed as attributes, which may or may not reflect
* changes made to the underlying document; most of these are
* self-explanatory from their names and types.
*/
[scriptable, uuid(74aa4918-5d15-46b6-9ccf-74f9696d721d)]
interface nsIWebBrowserPersistDocument : nsISupports
{
readonly attribute boolean isPrivate;
readonly attribute AUTF8String documentURI;
readonly attribute AUTF8String baseURI;
readonly attribute ACString contentType;
readonly attribute ACString characterSet;
readonly attribute AString title;
readonly attribute AString referrer;
readonly attribute AString contentDisposition;
readonly attribute nsIInputStream postData;
/**
* The cache key. Unlike in nsISHEntry, where it's wrapped in an
* nsISupportsPRUint32, this is just the integer.
*/
readonly attribute unsigned long cacheKey;
/**
* This attribute is set by nsIWebBrowserPersist implementations to
* propagate persist flags that apply to the DOM traversal and
* serialization (rather than to managing file I/O).
*/
attribute unsigned long persistFlags;
/**
* Walk the DOM searching for external resources needed to render it.
* The visitor callbacks may be called either before or after
* readResources returns.
*
* @see nsIWebBrowserPersistResourceVisitor
*/
void readResources(in nsIWebBrowserPersistResourceVisitor aVisitor);
/**
* Serialize the document's DOM.
*
* @param aStream The output stream to write the document to.
*
* @param aURIMap Optional; specifies URI rewriting to perform on
* external references (as read by readResources).
* If given, also causes relative hyperlinks to be
* converted to absolute in the written text.
*
* @param aRequestedContentType
* The desired MIME type to save the document as;
* optional and defaults to the document's type.
* (If no encoder exists for that type, "text/html"
* is used instead.)
*
* @param aEncoderFlags Flags to pass to the encoder.
*
* @param aWrapColumn Desired text width, ignored if wrapping is not
* specified by the encoding flags, or if 0.
*
* @param aCompletion Callback invoked when writing is complete.
* It may be called either before or after writeContent
* returns.
*
* @see nsIDocumentEncoder
*/
void writeContent(in nsIOutputStream aStream,
in nsIWebBrowserPersistURIMap aURIMap,
in ACString aRequestedContentType,
in unsigned long aEncoderFlags,
in unsigned long aWrapColumn,
in nsIWebBrowserPersistWriteCompletion aCompletion);
};
/**
* Asynchronous visitor that receives external resources linked by an
* nsIWebBrowserPersistDocument and which are needed to render the
* document.
*/
[scriptable, uuid(8ce37706-b7d3-481a-be68-54f174fc0d0a)]
interface nsIWebBrowserPersistResourceVisitor : nsISupports
{
/**
* Indicates a resource that is not a document; e.g., an image, script,
* or stylesheet.
*
* @param aDocument The document containing the reference.
* @param aURI The absolute URI spec for the referenced resource.
*/
void visitResource(in nsIWebBrowserPersistDocument aDocument,
in AUTF8String aURI);
/**
* Indicates a subdocument resource; e.g., a frame or iframe.
*
* @param aDocument The document containing the reference.
* @param aSubDocument The referenced document.
*/
void visitDocument(in nsIWebBrowserPersistDocument aDocument,
in nsIWebBrowserPersistDocument aSubDocument);
/**
* Indicates that the document traversal is complete.
*
* @param aDocument The document that was being traversed.
* @param aStatus Indicates whether the traversal encountered an error.
*/
void endVisit(in nsIWebBrowserPersistDocument aDocument,
in nsresult aStatus);
};
/**
* Asynchronous callback for when nsIWebBrowserPersistDocument is finished
* serializing the document's DOM.
*/
[scriptable, function, uuid(a07e6892-38ae-4207-8340-7fa6ec446ed6)]
interface nsIWebBrowserPersistWriteCompletion : nsISupports
{
/**
* Indicates that serialization is finished.
*
* @param aDocument The document that was being serialized.
*
* @param aStream The stream that was being written to. If it
* needs to be closed, the callback must do that;
* the serialization process leaves it open.
*
* @param aContentType The content type with which the document was
* actually serialized; this may be useful to set
* metadata on the result, or if uploading it.
*
* @param aStatus Indicates whether serialization encountered an error.
*/
void onFinish(in nsIWebBrowserPersistDocument aDocument,
in nsIOutputStream aStream,
in ACString aContentType,
in nsresult aStatus);
};
/**
* Asynchronous callback for creating a persistable document from some
* other object.
*
* @see nsIWebBrowserPersistable.
*/
[scriptable, uuid(321e3174-594f-4036-b7be-791b821bd376)]
interface nsIWebBrowserPersistDocumentReceiver : nsISupports
{
void onDocumentReady(in nsIWebBrowserPersistDocument aDocument);
void onError(in nsresult aFailure);
};

View file

@ -0,0 +1,41 @@
/* -*- Mode: IDL; 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 nsIWebBrowserPersistDocumentReceiver;
/**
* Interface for objects which represent a document that can be
* serialized with nsIWebBrowserPersist. This interface is
* asynchronous because the actual document can be in another process
* (e.g., if this object is an nsFrameLoader for an out-of-process
* frame).
*
* Warning: this is currently implemented only by nsFrameLoader, and
* may change in the future to become more frame-loader-specific or be
* merged into nsIFrameLoader. See bug 1101100 comment #34.
*
* @see nsIWebBrowserPersistDocumentReceiver
* @see nsIWebBrowserPersistDocument
* @see nsIWebBrowserPersist
*
* @param aOuterWindowID
* The outer window ID of the subframe we'd like to persist.
* If set at 0, nsIWebBrowserPersistable will attempt to persist
* the top-level document. If the outer window ID is for a subframe
* that does not exist, or is not held beneath the nsIWebBrowserPersistable,
* aRecv's onError method will be called with NS_ERROR_NO_CONTENT.
* @param aRecv
* The nsIWebBrowserPersistDocumentReceiver is a callback that
* will be fired once the document is ready for persisting.
*/
[scriptable, uuid(f4c3fa8e-83e9-49f8-ac6f-951fc7541fe4)]
interface nsIWebBrowserPersistable : nsISupports
{
void startPersistence(in unsigned long long aOuterWindowID,
in nsIWebBrowserPersistDocumentReceiver aRecv);
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,181 @@
/* -*- 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/. */
#ifndef nsWebBrowserPersist_h__
#define nsWebBrowserPersist_h__
#include "nsCOMPtr.h"
#include "nsWeakReference.h"
#include "nsIInterfaceRequestor.h"
#include "nsIMIMEService.h"
#include "nsIStreamListener.h"
#include "nsIOutputStream.h"
#include "nsIInputStream.h"
#include "nsIChannel.h"
#include "nsIDocumentEncoder.h"
#include "nsITransport.h"
#include "nsIProgressEventSink.h"
#include "nsIFile.h"
#include "nsIWebProgressListener2.h"
#include "nsIWebBrowserPersistDocument.h"
#include "mozilla/UniquePtr.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
#include "nsTArray.h"
#include "nsCWebBrowserPersist.h"
class nsIStorageStream;
class nsIWebBrowserPersistDocument;
class nsWebBrowserPersist final : public nsIInterfaceRequestor,
public nsIWebBrowserPersist,
public nsIStreamListener,
public nsIProgressEventSink,
public nsSupportsWeakReference
{
friend class nsEncoderNodeFixup;
// Public members
public:
nsWebBrowserPersist();
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICANCELABLE
NS_DECL_NSIWEBBROWSERPERSIST
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIPROGRESSEVENTSINK
// Private members
private:
virtual ~nsWebBrowserPersist();
nsresult SaveURIInternal(
nsIURI *aURI, nsISupports *aCacheKey, nsIURI *aReferrer,
uint32_t aReferrerPolicy, nsIInputStream *aPostData,
const char *aExtraHeaders, nsIURI *aFile,
bool aCalcFileExt, bool aIsPrivate);
nsresult SaveChannelInternal(
nsIChannel *aChannel, nsIURI *aFile, bool aCalcFileExt);
nsresult SaveDocumentInternal(
nsIWebBrowserPersistDocument *aDocument,
nsIURI *aFile,
nsIURI *aDataPath);
nsresult SaveDocuments();
void FinishSaveDocumentInternal(nsIURI* aFile, nsIFile* aDataPath);
nsresult GetExtensionForContentType(
const char16_t *aContentType, char16_t **aExt);
struct CleanupData;
struct DocData;
struct OutputData;
struct UploadData;
struct URIData;
struct WalkData;
struct URIFixupData;
class OnWalk;
class OnWrite;
class FlatURIMap;
friend class OnWalk;
friend class OnWrite;
nsresult SaveDocumentDeferred(mozilla::UniquePtr<WalkData>&& aData);
void Cleanup();
void CleanupLocalFiles();
nsresult GetValidURIFromObject(nsISupports *aObject, nsIURI **aURI) const;
static nsresult GetLocalFileFromURI(nsIURI *aURI, nsIFile **aLocalFile);
static nsresult AppendPathToURI(nsIURI *aURI, const nsAString & aPath);
nsresult MakeAndStoreLocalFilenameInURIMap(
nsIURI *aURI, bool aNeedsPersisting, URIData **aData);
nsresult MakeOutputStream(
nsIURI *aFile, nsIOutputStream **aOutputStream);
nsresult MakeOutputStreamFromFile(
nsIFile *aFile, nsIOutputStream **aOutputStream);
nsresult MakeOutputStreamFromURI(nsIURI *aURI, nsIOutputStream **aOutStream);
nsresult CreateChannelFromURI(nsIURI *aURI, nsIChannel **aChannel);
nsresult StartUpload(nsIStorageStream *aOutStream, nsIURI *aDestinationURI,
const nsACString &aContentType);
nsresult StartUpload(nsIInputStream *aInputStream, nsIURI *aDestinationURI,
const nsACString &aContentType);
nsresult CalculateAndAppendFileExt(nsIURI *aURI, nsIChannel *aChannel,
nsIURI *aOriginalURIWithExtension);
nsresult CalculateUniqueFilename(nsIURI *aURI);
nsresult MakeFilenameFromURI(
nsIURI *aURI, nsString &aFilename);
nsresult StoreURI(
const char *aURI,
bool aNeedsPersisting = true,
URIData **aData = nullptr);
nsresult StoreURI(
nsIURI *aURI,
bool aNeedsPersisting = true,
URIData **aData = nullptr);
bool DocumentEncoderExists(const char *aContentType);
nsresult SaveSubframeContent(
nsIWebBrowserPersistDocument *aFrameContent,
const nsCString& aURISpec,
URIData *aData);
nsresult SendErrorStatusChange(
bool aIsReadError, nsresult aResult, nsIRequest *aRequest, nsIURI *aURI);
nsresult FixRedirectedChannelEntry(nsIChannel *aNewChannel);
void EndDownload(nsresult aResult);
void FinishDownload();
void SerializeNextFile();
void CalcTotalProgress();
void SetApplyConversionIfNeeded(nsIChannel *aChannel);
nsCOMPtr<nsIURI> mCurrentDataPath;
bool mCurrentDataPathIsRelative;
nsCString mCurrentRelativePathToData;
nsCOMPtr<nsIURI> mCurrentBaseURI;
nsCString mCurrentCharset;
nsCOMPtr<nsIURI> mTargetBaseURI;
uint32_t mCurrentThingsToPersist;
nsCOMPtr<nsIMIMEService> mMIMEService;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIWebProgressListener> mProgressListener;
/**
* Progress listener for 64-bit values; this is the same object as
* mProgressListener, but is a member to avoid having to qi it for each
* progress notification.
*/
nsCOMPtr<nsIWebProgressListener2> mProgressListener2;
nsCOMPtr<nsIProgressEventSink> mEventSink;
nsClassHashtable<nsISupportsHashKey, OutputData> mOutputMap;
nsClassHashtable<nsISupportsHashKey, UploadData> mUploadList;
nsClassHashtable<nsCStringHashKey, URIData> mURIMap;
nsCOMPtr<nsIWebBrowserPersistURIMap> mFlatURIMap;
nsTArray<mozilla::UniquePtr<WalkData>> mWalkStack;
nsTArray<DocData*> mDocList;
nsTArray<CleanupData*> mCleanupList;
nsTArray<nsCString> mFilenameList;
bool mFirstAndOnlyUse;
bool mSavingDocument;
bool mCancel;
bool mCompleted;
bool mStartSaving;
bool mReplaceExisting;
bool mSerializingOutput;
bool mIsPrivate;
uint32_t mPersistFlags;
nsresult mPersistResult;
int64_t mTotalCurrentProgress;
int64_t mTotalMaxProgress;
int16_t mWrapColumn;
uint32_t mEncodingFlags;
nsString mContentType;
};
#endif

Some files were not shown because too many files have changed in this diff Show more