Bug 1399787 - Part 13. Handle AbortDocument.
While aborting conversion, we need to make sure there is no coversion task
executing in the PDFium process before destroying it.
MozReview-Commit-ID: 3Iqhe8KmYv2
--- a/gfx/thebes/PrintTargetEMF.cpp
+++ b/gfx/thebes/PrintTargetEMF.cpp
@@ -17,23 +17,24 @@ using mozilla::ipc::FileDescriptor;
namespace mozilla {
namespace gfx {
PrintTargetEMF::PrintTargetEMF(HDC aDC, const IntSize& aSize)
: PrintTarget(/* not using cairo_surface_t */ nullptr, aSize)
, mPDFiumProcess(nullptr)
, mPrinterDC(aDC)
+ , mWaitingForEMFConversion(false)
{
}
PrintTargetEMF::~PrintTargetEMF()
{
if (mPDFiumProcess) {
- mPDFiumProcess->Delete();
+ mPDFiumProcess->Delete(mWaitingForEMFConversion);
}
}
/* static */ already_AddRefed<PrintTargetEMF>
PrintTargetEMF::CreateOrNull(HDC aDC, const IntSize& aSizeInPoints)
{
return do_AddRef(new PrintTargetEMF(aDC, aSizeInPoints));
}
@@ -121,16 +122,17 @@ PrintTargetEMF::EndPage()
nsresult rv = mPDFFileForOnePage->OpenNSPRFileDesc(PR_RDONLY, PR_IRWXU,
&prfile);
NS_ENSURE_SUCCESS(rv, rv);
FileDescriptor descriptor(FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(prfile)));
mPDFiumProcess->GetActor()->SendConvertToEMF(descriptor,
::GetDeviceCaps(mPrinterDC, HORZRES),
::GetDeviceCaps(mPrinterDC, VERTRES));
PR_Close(prfile);
+ mWaitingForEMFConversion = true;
return NS_OK;
}
already_AddRefed<DrawTarget>
PrintTargetEMF::MakeDrawTarget(const IntSize& aSize,
DrawEventRecorder* aRecorder)
{
@@ -153,16 +155,17 @@ PrintTargetEMF::GetReferenceDrawTarget(D
}
void
PrintTargetEMF::ConvertToEMFDone(const nsresult& aResult,
mozilla::ipc::Shmem&& aEMF)
{
MOZ_ASSERT_IF(NS_FAILED(aResult), aEMF.Size<uint8_t>() == 0);
+ mWaitingForEMFConversion = false;
if (NS_SUCCEEDED(aResult)) {
if (::StartPage(mPrinterDC) > 0) {
mozilla::widget::WindowsEMF emf;
emf.InitFromFileContents(aEMF.get<BYTE>(), aEMF.Size<BYTE>());
RECT printRect = {0, 0, ::GetDeviceCaps(mPrinterDC, HORZRES),
::GetDeviceCaps(mPrinterDC, VERTRES)};
DebugOnly<bool> ret = emf.Playback(mPrinterDC, printRect);
MOZ_ASSERT(ret);
--- a/gfx/thebes/PrintTargetEMF.h
+++ b/gfx/thebes/PrintTargetEMF.h
@@ -62,14 +62,15 @@ private:
~PrintTargetEMF() override;
nsString mTitle;
RefPtr<PrintTargetSkPDF> mTargetForCurrentPage;
nsCOMPtr<nsIFile> mPDFFileForOnePage;
RefPtr<PrintTargetSkPDF> mRefTarget;
PDFiumProcessParent* mPDFiumProcess;
HDC mPrinterDC;
+ bool mWaitingForEMFConversion;
};
} // namespace gfx
} // namespace mozilla
#endif /* MOZILLA_GFX_PRINTTARGETEMF_H */
--- a/widget/windows/PDFiumParent.cpp
+++ b/widget/windows/PDFiumParent.cpp
@@ -24,29 +24,47 @@ PDFiumParent::Init(IPC::Channel* aChanne
AddRef();
return true;
}
void
PDFiumParent::ActorDestroy(ActorDestroyReason aWhy)
{
+ if (mConversionDoneCallback) {
+ // Since this printing job was aborted, we do not need to report EMF buffer
+ // back to mTarget.
+ mConversionDoneCallback();
+ }
}
mozilla::ipc::IPCResult
PDFiumParent::RecvConvertToEMFDone(const nsresult& aResult,
mozilla::ipc::Shmem&& aEMFContents)
{
MOZ_ASSERT(aEMFContents.IsReadable());
- mTarget->ConvertToEMFDone(aResult, Move(aEMFContents));
+
+ if (mTarget) {
+ MOZ_ASSERT(!mConversionDoneCallback);
+ mTarget->ConvertToEMFDone(aResult, Move(aEMFContents));
+ }
return IPC_OK();
}
void
+PDFiumParent::AbortConversion(ConversionDoneCallback aCallback)
+{
+ // There is no need to report EMF contents back to mTarget since the print
+ // job was aborted, unset mTarget.
+ mTarget = nullptr;
+ mConversionDoneCallback = aCallback;
+}
+
+void
PDFiumParent::OnChannelConnected(int32_t pid)
{
SetOtherProcessId(pid);
}
void
PDFiumParent::DeallocPPDFiumParent()
{
--- a/widget/windows/PDFiumParent.h
+++ b/widget/windows/PDFiumParent.h
@@ -18,32 +18,36 @@ namespace mozilla {
namespace widget {
class PDFiumParent final : public PPDFiumParent,
public mozilla::ipc::IShmemAllocator
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PDFiumParent)
typedef mozilla::gfx::PrintTargetEMF PrintTargetEMF;
+ typedef std::function<void()> ConversionDoneCallback;
explicit PDFiumParent(PrintTargetEMF* aTarget);
bool Init(IPC::Channel* aChannel, base::ProcessId aPid);
+ void AbortConversion(ConversionDoneCallback aCallback);
+
FORWARD_SHMEM_ALLOCATOR_TO(PPDFiumParent)
private:
~PDFiumParent() {}
// PPDFiumParent functions.
void ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult RecvConvertToEMFDone(const nsresult& aResult,
mozilla::ipc::Shmem&& aEMFContents) override;
void OnChannelConnected(int32_t pid) override;
void DeallocPPDFiumParent() override;
PrintTargetEMF* mTarget;
+ ConversionDoneCallback mConversionDoneCallback;
};
} // namespace widget
} // namespace mozilla
#endif // PDFIUMPARENT_H_
--- a/widget/windows/PDFiumProcessParent.cpp
+++ b/widget/windows/PDFiumProcessParent.cpp
@@ -44,30 +44,39 @@ PDFiumProcessParent::Launch(PrintTargetE
// Open the top level protocol for PDFium process.
MOZ_ASSERT(!mPDFiumParentActor);
mPDFiumParentActor = new PDFiumParent(aTarget);
return mPDFiumParentActor->Init(GetChannel(),
base::GetProcId(GetChildProcessHandle()));
}
void
-PDFiumProcessParent::Delete()
+PDFiumProcessParent::Delete(bool aWaitingForEMFConversion)
{
+ if (aWaitingForEMFConversion) {
+ // Can not kill the PDFium process yet since we are still waiting for a
+ // EMF conversion response.
+ mPDFiumParentActor->AbortConversion([this]() { Delete(false); });
+ mPDFiumParentActor->Close();
+ return;
+ }
+
// PDFiumProcessParent::Launch is not called, protocol is not created.
// It is safe to destroy this object on any thread.
if (!mLaunchThread) {
delete this;
return;
}
if (mLaunchThread == NS_GetCurrentThread()) {
delete this;
return;
}
mLaunchThread->Dispatch(
- NewNonOwningRunnableMethod("PDFiumProcessParent::Delete",
- this,
- &PDFiumProcessParent::Delete));
+ NewNonOwningRunnableMethod<bool>("PDFiumProcessParent::Delete",
+ this,
+ &PDFiumProcessParent::Delete,
+ false));
}
} // namespace widget
} // namespace mozilla
--- a/widget/windows/PDFiumProcessParent.h
+++ b/widget/windows/PDFiumProcessParent.h
@@ -32,17 +32,17 @@ class PDFiumProcessParent final : public
public:
typedef mozilla::gfx::PrintTargetEMF PrintTargetEMF;
PDFiumProcessParent();
~PDFiumProcessParent();
bool Launch(PrintTargetEMF* aTarget);
- void Delete();
+ void Delete(bool aWaitingForEMFConversion);
bool CanShutdown() override { return true; }
PDFiumParent* GetActor() const { return mPDFiumParentActor; }
private:
DISALLOW_COPY_AND_ASSIGN(PDFiumProcessParent);