Bug 1189846 Part 9: Add ability to print from the parent process with settings and progress listener. r=jimm, r=smaug

MozReview-Commit-ID: 7IEMByPmC0n
This commit is contained in:
Bob Owen 2016-05-16 10:40:54 +01:00
parent 80ef8208d0
commit 2d161a3465
12 changed files with 266 additions and 30 deletions

View File

@ -103,6 +103,11 @@
#include "nsXULPopupManager.h"
#endif
#ifdef NS_PRINTING
#include "mozilla/embedding/printingui/PrintingParent.h"
#include "nsIWebBrowserPrint.h"
#endif
using namespace mozilla;
using namespace mozilla::hal;
using namespace mozilla::dom;
@ -3102,6 +3107,46 @@ nsFrameLoader::RequestNotifyLayerTreeCleared()
return NS_OK;
}
NS_IMETHODIMP
nsFrameLoader::Print(nsIPrintSettings* aPrintSettings,
nsIWebProgressListener* aProgressListener)
{
#if defined(NS_PRINTING)
if (mRemoteBrowser) {
RefPtr<embedding::PrintingParent> printingParent =
mRemoteBrowser->Manager()->AsContentParent()->GetPrintingParent();
embedding::PrintData printData;
nsresult rv = printingParent->SerializeAndEnsureRemotePrintJob(
aPrintSettings, aProgressListener, nullptr, &printData);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool success = mRemoteBrowser->SendPrint(printData);
return success ? NS_OK : NS_ERROR_FAILURE;
}
if (mDocShell) {
nsCOMPtr<nsIContentViewer> viewer;
mDocShell->GetContentViewer(getter_AddRefs(viewer));
if (!viewer) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint = do_QueryInterface(viewer);
if (!webBrowserPrint) {
return NS_ERROR_FAILURE;
}
return webBrowserPrint->Print(aPrintSettings, aProgressListener);
}
return NS_ERROR_FAILURE;
#endif
return NS_OK;
}
/* [infallible] */ NS_IMETHODIMP
nsFrameLoader::SetVisible(bool aVisible)
{

View File

@ -16,6 +16,8 @@ interface nsIVariant;
interface nsIDOMElement;
interface nsITabParent;
interface nsILoadContext;
interface nsIPrintSettings;
interface nsIWebProgressListener;
[scriptable, builtinclass, uuid(1645af04-1bc7-4363-8f2c-eb9679220ab1)]
interface nsIFrameLoader : nsISupports
@ -139,6 +141,16 @@ interface nsIFrameLoader : nsISupports
void requestNotifyLayerTreeReady();
void requestNotifyLayerTreeCleared();
/**
* Print the current document.
*
* @param aPrintSettings optional print settings to use; printSilent can be
* set to prevent prompting.
* @param aProgressListener optional print progress listener.
*/
void print(in nsIPrintSettings aPrintSettings,
in nsIWebProgressListener aProgressListener);
/**
* The default event mode automatically forwards the events
* handled in EventStateManager::HandleCrossProcessEvent to

View File

@ -3846,6 +3846,17 @@ ContentParent::DeallocPPrintingParent(PPrintingParent* printing)
return true;
}
#ifdef NS_PRINTING
already_AddRefed<embedding::PrintingParent>
ContentParent::GetPrintingParent()
{
MOZ_ASSERT(mPrintingParent);
RefPtr<embedding::PrintingParent> printingParent = mPrintingParent;
return printingParent.forget();
}
#endif
PSendStreamParent*
ContentParent::AllocPSendStreamParent()
{

View File

@ -386,6 +386,13 @@ public:
virtual bool DeallocPPrintingParent(PPrintingParent* aActor) override;
#if defined(NS_PRINTING)
/**
* @return the PrintingParent for this ContentParent.
*/
already_AddRefed<embedding::PrintingParent> GetPrintingParent();
#endif
virtual PSendStreamParent* AllocPSendStreamParent() override;
virtual bool DeallocPSendStreamParent(PSendStreamParent* aActor) override;

View File

@ -15,10 +15,12 @@ include protocol PFilePicker;
include protocol PIndexedDBPermissionRequest;
include protocol PRenderFrame;
include protocol PPluginWidget;
include protocol PRemotePrintJob;
include DOMTypes;
include JavaScriptTypes;
include URIParams;
include BrowserConfiguration;
include PPrintingTypes;
include PTabContext;
@ -782,6 +784,13 @@ child:
async HandledWindowedPluginKeyEvent(NativeEventData aKeyEventData,
bool aIsConsumed);
/**
* Tell the child to print the current page with the given settings.
*
* @param aPrintData the serialized settings to print with
*/
async Print(PrintData aPrintData);
/*
* FIXME: write protocol!

View File

@ -112,6 +112,13 @@
#include "nsDeviceContext.h"
#include "FrameLayerBuilder.h"
#ifdef NS_PRINTING
#include "nsIPrintSession.h"
#include "nsIPrintSettings.h"
#include "nsIPrintSettingsService.h"
#include "nsIWebBrowserPrint.h"
#endif
#define BROWSER_ELEMENT_CHILD_SCRIPT \
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
@ -2435,6 +2442,45 @@ TabChild::RecvSetUseGlobalHistory(const bool& aUse)
return true;
}
bool
TabChild::RecvPrint(const PrintData& aPrintData)
{
#ifdef NS_PRINTING
nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint = do_GetInterface(mWebNav);
if (NS_WARN_IF(!webBrowserPrint)) {
return true;
}
nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1");
if (NS_WARN_IF(!printSettingsSvc)) {
return true;
}
nsCOMPtr<nsIPrintSettings> printSettings;
nsresult rv =
printSettingsSvc->GetNewPrintSettings(getter_AddRefs(printSettings));
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
nsCOMPtr<nsIPrintSession> printSession =
do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
printSettings->SetPrintSession(printSession);
printSettingsSvc->DeserializeToPrintSettings(aPrintData, printSettings);
rv = webBrowserPrint->Print(printSettings, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
#endif
return true;
}
bool
TabChild::RecvDestroy()
{

View File

@ -580,6 +580,8 @@ public:
const mozilla::NativeEventData& aKeyEventData,
const bool& aIsConsumed) override;
virtual bool RecvPrint(const PrintData& aPrintData) override;
/**
* Native widget remoting protocol for use with windowed plugins with e10s.
*/

View File

@ -11,7 +11,6 @@
#include "nsIDocument.h"
#include "nsIDOMWindow.h"
#include "nsIPrintingPromptService.h"
#include "nsIPrintOptions.h"
#include "nsIPrintProgressParams.h"
#include "nsIPrintSettingsService.h"
#include "nsIServiceManager.h"
@ -99,26 +98,22 @@ PrintingParent::ShowPrintDialog(PBrowserParent* aParent,
// nsIWebBrowserPrint to keep the dialogs happy.
nsCOMPtr<nsIWebBrowserPrint> wbp = new MockWebBrowserPrint(aData);
nsresult rv;
nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrintSettings> settings;
rv = printSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
nsresult rv = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
NS_ENSURE_SUCCESS(rv, rv);
rv = printSettingsSvc->DeserializeToPrintSettings(aData, settings);
rv = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings);
NS_ENSURE_SUCCESS(rv, rv);
rv = pps->ShowPrintDialog(parentWin, wbp, settings);
NS_ENSURE_SUCCESS(rv, rv);
// And send it back.
rv = printSettingsSvc->SerializeToPrintData(settings, nullptr, aResult);
PRemotePrintJobParent* remotePrintJob = new RemotePrintJobParent(settings);
aResult->remotePrintJobParent() = SendPRemotePrintJobConstructor(remotePrintJob);
// Serialize back to aResult. Use the existing RemotePrintJob if we have one
// otherwise SerializeAndEnsureRemotePrintJob() will create a new one.
RemotePrintJobParent* remotePrintJob =
static_cast<RemotePrintJobParent*>(aData.remotePrintJobParent());
rv = SerializeAndEnsureRemotePrintJob(settings, nullptr, remotePrintJob,
aResult);
return rv;
}
@ -149,18 +144,14 @@ PrintingParent::RecvSavePrintSettings(const PrintData& aData,
const uint32_t& aFlags,
nsresult* aResult)
{
nsCOMPtr<nsIPrintSettingsService> printSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1", aResult);
NS_ENSURE_SUCCESS(*aResult, true);
nsCOMPtr<nsIPrintSettings> settings;
*aResult = printSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
*aResult = mPrintSettingsSvc->GetNewPrintSettings(getter_AddRefs(settings));
NS_ENSURE_SUCCESS(*aResult, true);
*aResult = printSettingsSvc->DeserializeToPrintSettings(aData, settings);
*aResult = mPrintSettingsSvc->DeserializeToPrintSettings(aData, settings);
NS_ENSURE_SUCCESS(*aResult, true);
*aResult = printSettingsSvc->SavePrintSettingsToPrefs(settings,
*aResult = mPrintSettingsSvc->SavePrintSettingsToPrefs(settings,
aUsePrinterNamePrefix,
aFlags);
@ -249,14 +240,58 @@ PrintingParent::DOMWindowFromBrowserParent(PBrowserParent* parent)
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(aPrintSettings, 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);
MOZ_COUNT_CTOR(PrintingParent);
mPrintSettingsSvc =
do_GetService("@mozilla.org/gfx/printsettings-service;1");
MOZ_ASSERT(mPrintSettingsSvc);
}
PrintingParent::~PrintingParent()
{
MOZ_COUNT_DTOR(PrintingParent);
MOZ_COUNT_DTOR(PrintingParent);
}
} // namespace embedding

View File

@ -10,6 +10,8 @@
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/embedding/PPrintingParent.h"
class nsIPrintSettingsService;
class nsIWebProgressListener;
class nsPIDOMWindowOuter;
class PPrintProgressDialogParent;
class PPrintSettingsDialogParent;
@ -17,6 +19,7 @@ class PPrintSettingsDialogParent;
namespace mozilla {
namespace layout {
class PRemotePrintJobParent;
class RemotePrintJobParent;
}
namespace embedding {
@ -67,6 +70,25 @@ public:
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();
@ -77,6 +99,8 @@ private:
ShowPrintDialog(PBrowserParent* parent,
const PrintData& data,
PrintData* result);
nsCOMPtr<nsIPrintSettingsService> mPrintSettingsSvc;
};
} // namespace embedding

View File

@ -475,14 +475,29 @@ nsPrintEngine::DoCommonPrint(bool aIsPrintPreview,
}
// Create a print session and let the print settings know about it.
// Don't overwrite an existing print session.
// The print settings hold an nsWeakPtr to the session so it does not
// need to be cleared from the settings at the end of the job.
// XXX What lifetime does the printSession need to have?
nsCOMPtr<nsIPrintSession> printSession;
bool remotePrintJobListening = false;
if (!aIsPrintPreview) {
printSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
mPrt->mPrintSettings->SetPrintSession(printSession);
rv = mPrt->mPrintSettings->GetPrintSession(getter_AddRefs(printSession));
if (NS_FAILED(rv) || !printSession) {
printSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
mPrt->mPrintSettings->SetPrintSession(printSession);
} else {
RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
if (NS_SUCCEEDED(rv) && remotePrintJob) {
// If we have a RemotePrintJob add it to the print progress listeners,
// so it can forward to the parent.
mPrt->mPrintProgressListeners.AppendElement(remotePrintJob);
remotePrintJobListening = true;
}
}
}
if (aWebProgressListener != nullptr) {
@ -613,11 +628,15 @@ nsPrintEngine::DoCommonPrint(bool aIsPrintPreview,
// The user might have changed shrink-to-fit in the print dialog, so update our copy of its state
mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit);
// Add thee RemotePrintJob as a listener if there is one.
RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
if (NS_SUCCEEDED(rv) && remotePrintJob) {
mPrt->mPrintProgressListeners.AppendElement(remotePrintJob);
// If we haven't already added the RemotePrintJob as a listener,
// add it now if there is one.
if (!remotePrintJobListening) {
RefPtr<mozilla::layout::RemotePrintJobChild> remotePrintJob;
printSession->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
if (NS_SUCCEEDED(rv) && remotePrintJob) {
mPrt->mPrintProgressListeners.AppendElement(remotePrintJob);
remotePrintJobListening = true;
}
}
}
} else if (rv == NS_ERROR_NOT_IMPLEMENTED) {

View File

@ -1326,6 +1326,22 @@
</body>
</method>
<method name="print">
<parameter name="aPrintSettings"/>
<parameter name="aPrintProgressListener"/>
<body>
<![CDATA[
var owner = this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner);
if (!owner.frameLoader) {
throw Components.Exception("No frame loader.",
Components.results.NS_ERROR_FAILURE);
}
owner.frameLoader.print(aPrintSettings, aPrintProgressListener);
]]>
</body>
</method>
<!-- This will go away if the binding has been removed for some reason. -->
<field name="_alive">true</field>
</implementation>

View File

@ -105,6 +105,16 @@ nsPrintOptions::SerializeToPrintData(nsIPrintSettings* aSettings,
nsIWebBrowserPrint* aWBP,
PrintData* data)
{
nsCOMPtr<nsIPrintSession> session;
nsresult rv = aSettings->GetPrintSession(getter_AddRefs(session));
if (NS_SUCCEEDED(rv) && session) {
RefPtr<RemotePrintJobChild> remotePrintJob;
rv = session->GetRemotePrintJob(getter_AddRefs(remotePrintJob));
if (NS_SUCCEEDED(rv)) {
data->remotePrintJobChild() = remotePrintJob;
}
}
aSettings->GetStartPageRange(&data->startPageRange());
aSettings->GetEndPageRange(&data->endPageRange());