diff options
Diffstat (limited to '')
-rw-r--r-- | layout/printing/ipc/PRemotePrintJob.ipdl | 60 | ||||
-rw-r--r-- | layout/printing/ipc/RemotePrintJobChild.cpp | 167 | ||||
-rw-r--r-- | layout/printing/ipc/RemotePrintJobChild.h | 65 | ||||
-rw-r--r-- | layout/printing/ipc/RemotePrintJobParent.cpp | 295 | ||||
-rw-r--r-- | layout/printing/ipc/RemotePrintJobParent.h | 102 |
5 files changed, 689 insertions, 0 deletions
diff --git a/layout/printing/ipc/PRemotePrintJob.ipdl b/layout/printing/ipc/PRemotePrintJob.ipdl new file mode 100644 index 0000000000..bb1633e192 --- /dev/null +++ b/layout/printing/ipc/PRemotePrintJob.ipdl @@ -0,0 +1,60 @@ +/* -*- 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 protocol PPrinting; + +namespace mozilla { +namespace layout { + +async refcounted protocol PRemotePrintJob +{ + manager PPrinting; + +both: + // Tell either side to abort printing and clean up. + async AbortPrint(nsresult aRv); + +parent: + // Initialize the real print device with the given information. + async InitializePrint(nsString aDocumentTitle, nsString aPrintToFile, + int32_t aStartPage, int32_t aEndPage); + + // Translate the page recording writen into |fd| and play back the events to + // the real print device. + async ProcessPage(uint64_t[] deps); + + // This informs the real print device that we've finished, so it can trigger + // the actual print. + async FinalizePrint(); + + // Report a state change to listeners in the parent process. + async StateChange(long aStateFlags, + nsresult aStatus); + + // Report a progress change to listeners in the parent process. + async ProgressChange(long aCurSelfProgress, + long aMaxSelfProgress, + long aCurTotalProgress, + long aMaxTotalProgress); + + // Report a status change to listeners in the parent process. + async StatusChange(nsresult aStatus); + +child: + // Inform the child that the print has been initialized in the parent or has + // failed with result aRv. Includes a file descriptor which the first page + // can be written to. + async PrintInitializationResult(nsresult aRv, FileDescriptor aFd); + + // Inform the child that the latest page has been processed remotely. Includes + // a file descriptor which the next page can be written to. + async PageProcessed(FileDescriptor aFd); + + async __delete__(); +}; + +} // namespace layout +} // namespace mozilla diff --git a/layout/printing/ipc/RemotePrintJobChild.cpp b/layout/printing/ipc/RemotePrintJobChild.cpp new file mode 100644 index 0000000000..a7b7f5cfaa --- /dev/null +++ b/layout/printing/ipc/RemotePrintJobChild.cpp @@ -0,0 +1,167 @@ +/* -*- 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 "RemotePrintJobChild.h" + +#include "mozilla/SpinEventLoopUntil.h" +#include "mozilla/Unused.h" +#include "nsPagePrintTimer.h" +#include "nsPrintJob.h" +#include "private/pprio.h" + +namespace mozilla { +namespace layout { + +NS_IMPL_ISUPPORTS(RemotePrintJobChild, nsIWebProgressListener) + +RemotePrintJobChild::RemotePrintJobChild() = default; + +nsresult RemotePrintJobChild::InitializePrint(const nsString& aDocumentTitle, + const nsString& aPrintToFile, + const int32_t& aStartPage, + const int32_t& aEndPage) { + // Print initialization can sometimes display a dialog in the parent, so we + // need to spin a nested event loop until initialization completes. + Unused << SendInitializePrint(aDocumentTitle, aPrintToFile, aStartPage, + aEndPage); + mozilla::SpinEventLoopUntil([&]() { return mPrintInitialized; }); + + return mInitializationResult; +} + +mozilla::ipc::IPCResult RemotePrintJobChild::RecvPrintInitializationResult( + const nsresult& aRv, const mozilla::ipc::FileDescriptor& aFd) { + mPrintInitialized = true; + mInitializationResult = aRv; + if (NS_SUCCEEDED(aRv)) { + SetNextPageFD(aFd); + } + return IPC_OK(); +} + +PRFileDesc* RemotePrintJobChild::GetNextPageFD() { + MOZ_ASSERT(mNextPageFD); + PRFileDesc* fd = mNextPageFD; + mNextPageFD = nullptr; + return fd; +} + +void RemotePrintJobChild::SetNextPageFD( + const mozilla::ipc::FileDescriptor& aFd) { + auto handle = aFd.ClonePlatformHandle(); + mNextPageFD = PR_ImportFile(PROsfd(handle.release())); +} + +void RemotePrintJobChild::ProcessPage(nsTArray<uint64_t>&& aDeps) { + MOZ_ASSERT(mPagePrintTimer); + + mPagePrintTimer->WaitForRemotePrint(); + if (!mDestroyed) { + Unused << SendProcessPage(std::move(aDeps)); + } +} + +mozilla::ipc::IPCResult RemotePrintJobChild::RecvPageProcessed( + const mozilla::ipc::FileDescriptor& aFd) { + MOZ_ASSERT(mPagePrintTimer); + SetNextPageFD(aFd); + + mPagePrintTimer->RemotePrintFinished(); + return IPC_OK(); +} + +mozilla::ipc::IPCResult RemotePrintJobChild::RecvAbortPrint( + const nsresult& aRv) { + MOZ_ASSERT(mPrintJob); + + mPrintJob->CleanupOnFailure(aRv, true); + return IPC_OK(); +} + +void RemotePrintJobChild::SetPagePrintTimer(nsPagePrintTimer* aPagePrintTimer) { + MOZ_ASSERT(aPagePrintTimer); + + mPagePrintTimer = aPagePrintTimer; +} + +void RemotePrintJobChild::SetPrintJob(nsPrintJob* aPrintJob) { + MOZ_ASSERT(aPrintJob); + + mPrintJob = aPrintJob; +} + +// nsIWebProgressListener + +NS_IMETHODIMP +RemotePrintJobChild::OnStateChange(nsIWebProgress* aProgress, + nsIRequest* aRequest, uint32_t aStateFlags, + nsresult aStatus) { + if (!mDestroyed) { + Unused << SendStateChange(aStateFlags, aStatus); + } + + return NS_OK; +} + +NS_IMETHODIMP +RemotePrintJobChild::OnProgressChange(nsIWebProgress* aProgress, + nsIRequest* aRequest, + int32_t aCurSelfProgress, + int32_t aMaxSelfProgress, + int32_t aCurTotalProgress, + int32_t aMaxTotalProgress) { + if (!mDestroyed) { + Unused << SendProgressChange(aCurSelfProgress, aMaxSelfProgress, + aCurTotalProgress, aMaxTotalProgress); + } + + return NS_OK; +} + +NS_IMETHODIMP +RemotePrintJobChild::OnLocationChange(nsIWebProgress* aProgress, + nsIRequest* aRequest, nsIURI* aURI, + uint32_t aFlags) { + return NS_OK; +} + +NS_IMETHODIMP +RemotePrintJobChild::OnStatusChange(nsIWebProgress* aProgress, + nsIRequest* aRequest, nsresult aStatus, + const char16_t* aMessage) { + if (NS_SUCCEEDED(mInitializationResult) && !mDestroyed) { + Unused << SendStatusChange(aStatus); + } + + return NS_OK; +} + +NS_IMETHODIMP +RemotePrintJobChild::OnSecurityChange(nsIWebProgress* aProgress, + nsIRequest* aRequest, uint32_t aState) { + return NS_OK; +} + +NS_IMETHODIMP +RemotePrintJobChild::OnContentBlockingEvent(nsIWebProgress* aProgress, + nsIRequest* aRequest, + uint32_t aEvent) { + return NS_OK; +} + +// End of nsIWebProgressListener + +RemotePrintJobChild::~RemotePrintJobChild() = default; + +void RemotePrintJobChild::ActorDestroy(ActorDestroyReason aWhy) { + mPagePrintTimer = nullptr; + mPrintJob = nullptr; + + mDestroyed = true; +} + +} // namespace layout +} // namespace mozilla diff --git a/layout/printing/ipc/RemotePrintJobChild.h b/layout/printing/ipc/RemotePrintJobChild.h new file mode 100644 index 0000000000..7e046977b6 --- /dev/null +++ b/layout/printing/ipc/RemotePrintJobChild.h @@ -0,0 +1,65 @@ +/* -*- 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 mozilla_layout_RemotePrintJobChild_h +#define mozilla_layout_RemotePrintJobChild_h + +#include "mozilla/layout/PRemotePrintJobChild.h" + +#include "mozilla/RefPtr.h" +#include "nsIWebProgressListener.h" + +class nsPagePrintTimer; +class nsPrintJob; + +namespace mozilla { +namespace layout { + +class RemotePrintJobChild final : public PRemotePrintJobChild, + public nsIWebProgressListener { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIWEBPROGRESSLISTENER + + RemotePrintJobChild(); + + void ActorDestroy(ActorDestroyReason aWhy) final; + + nsresult InitializePrint(const nsString& aDocumentTitle, + const nsString& aPrintToFile, + const int32_t& aStartPage, const int32_t& aEndPage); + + mozilla::ipc::IPCResult RecvPrintInitializationResult( + const nsresult& aRv, const FileDescriptor& aFd) final; + + void ProcessPage(nsTArray<uint64_t>&& aDeps); + + mozilla::ipc::IPCResult RecvPageProcessed(const FileDescriptor& aFd) final; + + mozilla::ipc::IPCResult RecvAbortPrint(const nsresult& aRv) final; + + void SetPagePrintTimer(nsPagePrintTimer* aPagePrintTimer); + + void SetPrintJob(nsPrintJob* aPrintJob); + + PRFileDesc* GetNextPageFD(); + + private: + ~RemotePrintJobChild() final; + void SetNextPageFD(const mozilla::ipc::FileDescriptor& aFd); + + bool mPrintInitialized = false; + bool mDestroyed = false; + nsresult mInitializationResult = NS_OK; + RefPtr<nsPagePrintTimer> mPagePrintTimer; + RefPtr<nsPrintJob> mPrintJob; + PRFileDesc* mNextPageFD = nullptr; +}; + +} // namespace layout +} // namespace mozilla + +#endif // mozilla_layout_RemotePrintJobChild_h diff --git a/layout/printing/ipc/RemotePrintJobParent.cpp b/layout/printing/ipc/RemotePrintJobParent.cpp new file mode 100644 index 0000000000..4e9ca0ed0d --- /dev/null +++ b/layout/printing/ipc/RemotePrintJobParent.cpp @@ -0,0 +1,295 @@ +/* -*- 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 "RemotePrintJobParent.h" + +#include <fstream> + +#include "gfxContext.h" +#include "mozilla/Attributes.h" +#include "mozilla/Unused.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsComponentManagerUtils.h" +#include "nsDirectoryServiceUtils.h" +#include "nsDeviceContext.h" +#include "nsIDeviceContextSpec.h" +#include "nsIPrintSettings.h" +#include "nsIWebProgressListener.h" +#include "PrintTranslator.h" +#include "private/pprio.h" +#include "nsAnonymousTemporaryFile.h" + +namespace mozilla { +namespace layout { + +RemotePrintJobParent::RemotePrintJobParent(nsIPrintSettings* aPrintSettings) + : mPrintSettings(aPrintSettings), mIsDoingPrinting(false) { + MOZ_COUNT_CTOR(RemotePrintJobParent); +} + +mozilla::ipc::IPCResult RemotePrintJobParent::RecvInitializePrint( + const nsString& aDocumentTitle, const nsString& aPrintToFile, + const int32_t& aStartPage, const int32_t& aEndPage) { + nsresult rv = + InitializePrintDevice(aDocumentTitle, aPrintToFile, aStartPage, aEndPage); + if (NS_FAILED(rv)) { + Unused << SendPrintInitializationResult(rv, FileDescriptor()); + // Let any listeners know about the failure before we delete. + Unused << RecvStatusChange(rv); + Unused << Send__delete__(this); + return IPC_OK(); + } + + mPrintTranslator.reset(new PrintTranslator(mPrintDeviceContext)); + FileDescriptor fd; + rv = PrepareNextPageFD(&fd); + if (NS_FAILED(rv)) { + Unused << SendPrintInitializationResult(rv, FileDescriptor()); + // Let any listeners know about the failure before we delete. + Unused << RecvStatusChange(rv); + Unused << Send__delete__(this); + return IPC_OK(); + } + + Unused << SendPrintInitializationResult(NS_OK, fd); + return IPC_OK(); +} + +nsresult RemotePrintJobParent::InitializePrintDevice( + const nsString& aDocumentTitle, const nsString& aPrintToFile, + const int32_t& aStartPage, const int32_t& aEndPage) { + nsresult rv; + nsCOMPtr<nsIDeviceContextSpec> deviceContextSpec = + do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = deviceContextSpec->Init(nullptr, mPrintSettings, false); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + mPrintDeviceContext = new nsDeviceContext(); + rv = mPrintDeviceContext->InitForPrinting(deviceContextSpec); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = mPrintDeviceContext->BeginDocument(aDocumentTitle, aPrintToFile, + aStartPage, aEndPage); + if (NS_FAILED(rv)) { + NS_WARNING_ASSERTION(rv == NS_ERROR_ABORT, + "Failed to initialize print device"); + return rv; + } + + if (!mPrintDeviceContext->IsSyncPagePrinting()) { + mPrintDeviceContext->RegisterPageDoneCallback( + [self = RefPtr{this}](nsresult aResult) { self->PageDone(aResult); }); + } + + mIsDoingPrinting = true; + + return NS_OK; +} + +nsresult RemotePrintJobParent::PrepareNextPageFD(FileDescriptor* aFd) { + PRFileDesc* prFd = nullptr; + nsresult rv = NS_OpenAnonymousTemporaryFile(&prFd); + if (NS_FAILED(rv)) { + return rv; + } + *aFd = FileDescriptor( + FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(prFd))); + mCurrentPageStream.OpenFD(prFd); + return NS_OK; +} + +mozilla::ipc::IPCResult RemotePrintJobParent::RecvProcessPage( + nsTArray<uint64_t>&& aDeps) { + if (!mCurrentPageStream.IsOpen()) { + Unused << SendAbortPrint(NS_ERROR_FAILURE); + return IPC_OK(); + } + mCurrentPageStream.Seek(0, PR_SEEK_SET); + + if (aDeps.IsEmpty()) { + FinishProcessingPage(); + return IPC_OK(); + } + + nsTHashtable<nsUint64HashKey> deps; + for (auto i : aDeps) { + deps.PutEntry(i); + } + + gfx::CrossProcessPaint::Start(std::move(deps)) + ->Then( + GetCurrentSerialEventTarget(), __func__, + [self = RefPtr{this}]( + gfx::CrossProcessPaint::ResolvedFragmentMap&& aFragments) { + self->FinishProcessingPage(&aFragments); + }, + [self = RefPtr{this}](const nsresult& aRv) { + self->FinishProcessingPage(); + }); + + return IPC_OK(); +} + +void RemotePrintJobParent::FinishProcessingPage( + gfx::CrossProcessPaint::ResolvedFragmentMap* aFragments) { + nsresult rv = PrintPage(mCurrentPageStream, aFragments); + + mCurrentPageStream.Close(); + + if (mPrintDeviceContext->IsSyncPagePrinting()) { + PageDone(rv); + } +} + +nsresult RemotePrintJobParent::PrintPage( + PRFileDescStream& aRecording, + gfx::CrossProcessPaint::ResolvedFragmentMap* aFragments) { + MOZ_ASSERT(mPrintDeviceContext); + + nsresult rv = mPrintDeviceContext->BeginPage(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + if (aFragments) { + mPrintTranslator->SetDependentSurfaces(std::move(*aFragments)); + } + if (!mPrintTranslator->TranslateRecording(aRecording)) { + return NS_ERROR_FAILURE; + } + + rv = mPrintDeviceContext->EndPage(); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + +void RemotePrintJobParent::PageDone(nsresult aResult) { + MOZ_ASSERT(mIsDoingPrinting); + + if (NS_FAILED(aResult)) { + Unused << SendAbortPrint(aResult); + } else { + FileDescriptor fd; + aResult = PrepareNextPageFD(&fd); + if (NS_FAILED(aResult)) { + Unused << SendAbortPrint(aResult); + } + + Unused << SendPageProcessed(fd); + } +} + +mozilla::ipc::IPCResult RemotePrintJobParent::RecvFinalizePrint() { + // EndDocument is sometimes called in the child even when BeginDocument has + // not been called. See bug 1223332. + if (mPrintDeviceContext) { + DebugOnly<nsresult> rv = mPrintDeviceContext->EndDocument(); + + // Too late to abort the child just log. + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "EndDocument failed"); + + // Since RecvFinalizePrint is called after all page printed, there should + // be no more page-done callbacks after that, in theory. Unregistering + // page-done callback is not must have, but we still do this for safety. + mPrintDeviceContext->UnregisterPageDoneCallback(); + } + + mIsDoingPrinting = false; + + Unused << Send__delete__(this); + return IPC_OK(); +} + +mozilla::ipc::IPCResult RemotePrintJobParent::RecvAbortPrint( + const nsresult& aRv) { + if (mPrintDeviceContext) { + Unused << mPrintDeviceContext->AbortDocument(); + mPrintDeviceContext->UnregisterPageDoneCallback(); + } + + mIsDoingPrinting = false; + + Unused << Send__delete__(this); + return IPC_OK(); +} + +mozilla::ipc::IPCResult RemotePrintJobParent::RecvStateChange( + const long& aStateFlags, const nsresult& aStatus) { + uint32_t numberOfListeners = mPrintProgressListeners.Length(); + for (uint32_t i = 0; i < numberOfListeners; ++i) { + nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i); + listener->OnStateChange(nullptr, nullptr, aStateFlags, aStatus); + } + + return IPC_OK(); +} + +mozilla::ipc::IPCResult RemotePrintJobParent::RecvProgressChange( + const long& aCurSelfProgress, const long& aMaxSelfProgress, + const long& aCurTotalProgress, const long& aMaxTotalProgress) { + uint32_t numberOfListeners = mPrintProgressListeners.Length(); + for (uint32_t i = 0; i < numberOfListeners; ++i) { + nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i); + listener->OnProgressChange(nullptr, nullptr, aCurSelfProgress, + aMaxSelfProgress, aCurTotalProgress, + aMaxTotalProgress); + } + + return IPC_OK(); +} + +mozilla::ipc::IPCResult RemotePrintJobParent::RecvStatusChange( + const nsresult& aStatus) { + uint32_t numberOfListeners = mPrintProgressListeners.Length(); + for (uint32_t i = 0; i < numberOfListeners; ++i) { + nsIWebProgressListener* listener = mPrintProgressListeners.SafeElementAt(i); + listener->OnStatusChange(nullptr, nullptr, aStatus, nullptr); + } + + return IPC_OK(); +} + +void RemotePrintJobParent::RegisterListener(nsIWebProgressListener* aListener) { + MOZ_ASSERT(aListener); + + mPrintProgressListeners.AppendElement(aListener); +} + +already_AddRefed<nsIPrintSettings> RemotePrintJobParent::GetPrintSettings() { + nsCOMPtr<nsIPrintSettings> printSettings = mPrintSettings; + return printSettings.forget(); +} + +RemotePrintJobParent::~RemotePrintJobParent() { + MOZ_COUNT_DTOR(RemotePrintJobParent); +} + +void RemotePrintJobParent::ActorDestroy(ActorDestroyReason aWhy) { + if (mPrintDeviceContext) { + mPrintDeviceContext->UnregisterPageDoneCallback(); + } + + mIsDoingPrinting = false; + + // If progress dialog is opened, notify closing it. + for (auto listener : mPrintProgressListeners) { + listener->OnStateChange(nullptr, nullptr, + nsIWebProgressListener::STATE_STOP, NS_OK); + } +} + +} // namespace layout +} // namespace mozilla diff --git a/layout/printing/ipc/RemotePrintJobParent.h b/layout/printing/ipc/RemotePrintJobParent.h new file mode 100644 index 0000000000..df7b3dd51f --- /dev/null +++ b/layout/printing/ipc/RemotePrintJobParent.h @@ -0,0 +1,102 @@ +/* -*- 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 mozilla_layout_RemotePrintJobParent_h +#define mozilla_layout_RemotePrintJobParent_h + +#include "mozilla/layout/PRemotePrintJobParent.h" +#include "mozilla/layout/printing/DrawEventRecorder.h" + +#include "nsCOMArray.h" +#include "nsCOMPtr.h" +#include "mozilla/RefPtr.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/gfx/RecordedEvent.h" +#include "mozilla/gfx/CrossProcessPaint.h" + +class nsDeviceContext; +class nsIPrintSettings; +class nsIWebProgressListener; + +namespace mozilla { +namespace layout { + +class PrintTranslator; + +class RemotePrintJobParent final : public PRemotePrintJobParent { + public: + NS_INLINE_DECL_REFCOUNTING(RemotePrintJobParent); + + explicit RemotePrintJobParent(nsIPrintSettings* aPrintSettings); + + void ActorDestroy(ActorDestroyReason aWhy) final; + + mozilla::ipc::IPCResult RecvInitializePrint(const nsString& aDocumentTitle, + const nsString& aPrintToFile, + const int32_t& aStartPage, + const int32_t& aEndPage) final; + + mozilla::ipc::IPCResult RecvProcessPage(nsTArray<uint64_t>&& aDeps) final; + + mozilla::ipc::IPCResult RecvFinalizePrint() final; + + mozilla::ipc::IPCResult RecvAbortPrint(const nsresult& aRv) final; + + mozilla::ipc::IPCResult RecvStateChange(const long& aStateFlags, + const nsresult& aStatus) final; + + mozilla::ipc::IPCResult RecvProgressChange( + const long& aCurSelfProgress, const long& aMaxSelfProgress, + const long& aCurTotalProgress, const long& aMaxTotalProgress) final; + + mozilla::ipc::IPCResult RecvStatusChange(const nsresult& aStatus) final; + + /** + * Register a progress listener to receive print progress updates. + * + * @param aListener the progress listener to register. Must not be null. + */ + void RegisterListener(nsIWebProgressListener* aListener); + + /** + * @return the print settings for this remote print job. + */ + already_AddRefed<nsIPrintSettings> GetPrintSettings(); + + private: + ~RemotePrintJobParent() final; + + nsresult InitializePrintDevice(const nsString& aDocumentTitle, + const nsString& aPrintToFile, + const int32_t& aStartPage, + const int32_t& aEndPage); + + nsresult PrepareNextPageFD(FileDescriptor* aFd); + + nsresult PrintPage( + PRFileDescStream& aRecording, + gfx::CrossProcessPaint::ResolvedFragmentMap* aFragments = nullptr); + void FinishProcessingPage( + gfx::CrossProcessPaint::ResolvedFragmentMap* aFragments = nullptr); + + /** + * Called to notify our corresponding RemotePrintJobChild once we've + * finished printing a page. + */ + void PageDone(nsresult aResult); + + nsCOMPtr<nsIPrintSettings> mPrintSettings; + RefPtr<nsDeviceContext> mPrintDeviceContext; + UniquePtr<PrintTranslator> mPrintTranslator; + nsCOMArray<nsIWebProgressListener> mPrintProgressListeners; + PRFileDescStream mCurrentPageStream; + bool mIsDoingPrinting; +}; + +} // namespace layout +} // namespace mozilla + +#endif // mozilla_layout_RemotePrintJobParent_h |