Bug 1399787 - Part 3. Create a top level protocol for the PDFium process. draft
authorcku <cku@mozilla.com>
Fri, 13 Oct 2017 16:58:07 +0800
changeset 710599 0f4cbff19ae5cd34f8ab9a0fa8e1fa8b115a3f73
parent 710598 c31ab60b22833cd992d50a82f894085223c7fa55
child 710600 9432131ddf243b2644ab07fb076776dcee4486f8
push id92855
push usercku@mozilla.com
push dateMon, 11 Dec 2017 02:44:26 +0000
bugs1399787, 1370488
milestone59.0a1
Bug 1399787 - Part 3. Create a top level protocol for the PDFium process. Define ipdl and actor classes. Implementation of actors is added in subsequent patches. Control flow: 1. A user starts a printing job. 2. We create a PrintTarget to print web content page by page. 3. When printing pages: a. PrintTarget, who lives in the chrome process, create a new FileDescriptor and pass that FD to the content process. b. The content process renders page contents into the given FD. c. PrintTarget render that FD, which contains only one page, into a PDF file. d. PrintTaget asks PDFium process to convert that PDF file into EMF contents by *ConvertToEMF* e. The PDFium process converts the given PDF into EMF contents and send back EMF contents by *ConvertToEMFDone* f. PrintTaget playbacks that EMF onto a printer DC. One page is printed! f. If all pages are printed, then finalize print job; Otherwise, loop back to #a. The control flow that we landed in bug 1370488 does not work like the flow I described above. In [1], we paint all pages into one single PDF file. After all pages are rendered into this PDF file, we finalize the current print job, which means the printing progress dialog is close. *Then* we start to convert that PDF into EMF and print each EMF page onto printer DC. We can not cancel this conversion task since the printing dialog is close, there is no UI allow us to do that. One more serious problem is: since the printing progress dialog is close, people think that printing is done, but actually it's not. Except move EMF conversion to a dedicated process, named PDFium process, I will also fix the behavior we landed in bug 1370488. [1] https://hg.mozilla.org/mozilla-central/rev/b611ec2a42bf MozReview-Commit-ID: JAnmNc3gAVK
widget/windows/PDFiumChild.cpp
widget/windows/PDFiumChild.h
widget/windows/PDFiumParent.cpp
widget/windows/PDFiumParent.h
widget/windows/PPDFium.ipdl
widget/windows/moz.build
new file mode 100644
--- /dev/null
+++ b/widget/windows/PDFiumChild.cpp
@@ -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/. */
+
+#include "PDFiumChild.h"
+#include "nsLocalFile.h"
+#include "mozilla/widget/PDFViaEMFPrintHelper.h"
+
+namespace mozilla {
+namespace widget {
+
+PDFiumChild::PDFiumChild()
+{
+}
+
+PDFiumChild::~PDFiumChild()
+{
+}
+
+bool
+PDFiumChild::Init(base::ProcessId aParentPid,
+                  MessageLoop* aIOLoop,
+                  IPC::Channel* aChannel)
+{
+  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
+    return false;
+  }
+
+  return true;
+}
+
+mozilla::ipc::IPCResult
+PDFiumChild::RecvConvertToEMF(const FileDescriptor& aFD,
+                              const int& aPageWidth,
+                              const int& aPageHeight)
+{
+  MOZ_ASSERT(aFD.IsValid() && aPageWidth != 0 && aPageHeight != 0);
+
+  // TBD: Initiate PDFium library.
+
+  return IPC_OK();
+}
+
+void
+PDFiumChild::OnChannelConnected(int32_t pid)
+{
+  SetOtherProcessId(pid);
+}
+
+void
+PDFiumChild::ActorDestroy(ActorDestroyReason why)
+{
+  XRE_ShutdownChildProcess();
+}
+
+} // namespace widget
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/widget/windows/PDFiumChild.h
@@ -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/. */
+
+#ifndef PDFIUMCHILD_H_
+#define PDFIUMCHILD_H_
+
+#include "mozilla/widget/PPDFiumChild.h"
+
+namespace mozilla {
+namespace widget {
+
+class PDFiumChild final : public PPDFiumChild {
+public:
+  PDFiumChild();
+  virtual ~PDFiumChild();
+
+  bool Init(base::ProcessId aParentPid,
+            MessageLoop* aIOLoop,
+            IPC::Channel* aChannel);
+
+private:
+  // PPDFiumChild functions.
+  mozilla::ipc::IPCResult RecvConvertToEMF(const FileDescriptor& aFD,
+                                           const int& aPageWidth,
+                                           const int& aPageHeight) override;
+  void ActorDestroy(ActorDestroyReason aWhy) override;
+  void OnChannelConnected(int32_t pid) override;
+};
+
+} // namespace widget
+} // namespace mozilla
+
+#endif // PDFIUMCHILD_H_
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/widget/windows/PDFiumParent.cpp
@@ -0,0 +1,55 @@
+/* -*- 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 "PDFiumParent.h"
+#include "nsDeviceContextSpecWin.h"
+
+namespace mozilla {
+namespace widget {
+
+PDFiumParent::PDFiumParent()
+{
+}
+
+bool
+PDFiumParent::Init(IPC::Channel* aChannel, base::ProcessId aPid)
+{
+  if (NS_WARN_IF(!Open(aChannel, aPid))) {
+    return false;
+  }
+
+  AddRef();
+  return true;
+}
+
+void
+PDFiumParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+}
+
+mozilla::ipc::IPCResult
+PDFiumParent::RecvConvertToEMFDone(const nsresult& aResult,
+                                   mozilla::ipc::Shmem&& aEMFContents)
+{
+  MOZ_ASSERT(aEMFContents.IsReadable());
+  // TBD: playback aEMFContents onto printer DC.
+
+  return IPC_OK();
+}
+
+void
+PDFiumParent::OnChannelConnected(int32_t pid)
+{
+  SetOtherProcessId(pid);
+}
+
+void
+PDFiumParent::DeallocPPDFiumParent()
+{
+  Release();
+}
+
+} // namespace widget
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/widget/windows/PDFiumParent.h
@@ -0,0 +1,38 @@
+/* -*- 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 PDFIUMPARENT_H_
+#define PDFIUMPARENT_H_
+
+#include "mozilla/widget/PPDFiumParent.h"
+
+
+namespace mozilla {
+namespace widget {
+
+class PDFiumParent final : public PPDFiumParent {
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PDFiumParent)
+
+  explicit PDFiumParent();
+
+  bool Init(IPC::Channel* aChannel, base::ProcessId aPid);
+
+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;
+};
+
+} // namespace widget
+} // namespace mozilla
+
+#endif // PDFIUMPARENT_H_
new file mode 100644
--- /dev/null
+++ b/widget/windows/PPDFium.ipdl
@@ -0,0 +1,32 @@
+/* -*- 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/. */
+
+namespace mozilla {
+namespace widget {
+
+
+/**
+ * A protocol for communicating with the PDFium processes. Useful for
+ * converting a PDF file to EMF contents.
+ *
+ * PDFium processes are created on-demand as necessary.
+ */
+protocol PPDFium
+{
+parent:
+  /**
+   * Called by the PDFium process once the PDF has been converted to EMF.
+   */
+  async ConvertToEMFDone(nsresult aResult, Shmem aEMFContents);
+
+child:
+  /**
+   * Start to convert a PDF file to EMF contents.
+   */
+  async ConvertToEMF(FileDescriptor aFD, int aPageWidth, int aPageHeight);
+};
+
+} // namespace widget
+} // namespace mozilla
--- a/widget/windows/moz.build
+++ b/widget/windows/moz.build
@@ -18,17 +18,19 @@ EXPORTS += [
     'WinUtils.h',
 ]
 
 EXPORTS.mozilla.widget += [
     'AudioSession.h',
     'CompositorWidgetChild.h',
     'CompositorWidgetParent.h',
     'InProcessWinCompositorWidget.h',
+    'PDFiumChild.h',
     'PDFiumEngineShim.h',
+    'PDFiumParent.h',
     'PDFViaEMFPrintHelper.h',
     'WinCompositorWidget.h',
     'WinMessages.h',
     'WinModifierKeyState.h',
     'WinNativeEventData.h',
 ]
 
 UNIFIED_SOURCES += [
@@ -91,20 +93,26 @@ SOURCES += [
 if CONFIG['NS_PRINTING']:
     UNIFIED_SOURCES += [
         'nsDeviceContextSpecWin.cpp',
         'nsPrintDialogUtil.cpp',
         'nsPrintDialogWin.cpp',
         'nsPrintOptionsWin.cpp',
         'nsPrintSettingsWin.cpp',
     ]
+
 if CONFIG['MOZ_ENABLE_SKIA_PDF']:
     DIRS += ['/modules/pdfium']
+    IPDL_SOURCES += [
+        'PPDFium.ipdl',
+    ]
     UNIFIED_SOURCES += [
+        'PDFiumChild.cpp',
         'PDFiumEngineShim.cpp',
+        'PDFiumParent.cpp',
         'PDFViaEMFPrintHelper.cpp',
         'WindowsEMF.cpp',
     ]
 
 if CONFIG['NS_ENABLE_TSF']:
     SOURCES += [
         'TSFTextStore.cpp',
     ]