[go: nahoru, domu]

M123: Update OOPPD GDI metafile handling for PostScript

Relocate the PostScriptMetafile class out from the anonymous scope of
PDF converter implementation and make it a public class.  This enables
the Print Backend service to use that when appropriate for print jobs
where the conversion was made to store PostScript data inside of an EMF
wrapper.  Include some style corrections to the code as well.

Update PostScriptMetafile to override GetDataType(), to signify that
its data is a different type of EMF object compared to what is handled
by the base class.

Using the correct EMF class for the data ensures that the correct
playback method is used against the data, so that the desired imaging
is achieved.  This allows the test expectations for
SystemAccessProcessSandboxedServicePrintBrowserTest to similarly
succeed for all printer language types.

(cherry picked from commit d03e5918c6acd61aff60c66a521b6b8c328bc30c)

Bug: 41492268
Change-Id: I5dfddff94dfad9b65f5cc4f39496d372e6a607b4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5331976
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Alan Screen <awscreen@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1268742}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5362284
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/branch-heads/6312@{#539}
Cr-Branched-From: 6711dcdae48edaf98cbc6964f90fac85b7d9986e-refs/heads/main@{#1262506}
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc
index 1f8c3cc..6220dd2 100644
--- a/chrome/browser/printing/pdf_to_emf_converter.cc
+++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -42,22 +42,6 @@
 
 namespace {
 
-// Emf subclass that knows how to play back PostScript data embedded as EMF
-// comment records.
-class PostScriptMetaFile : public Emf {
- public:
-  PostScriptMetaFile() = default;
-
-  PostScriptMetaFile(const PostScriptMetaFile&) = delete;
-  PostScriptMetaFile& operator=(const PostScriptMetaFile&) = delete;
-
-  ~PostScriptMetaFile() override = default;
-
- private:
-  // Emf:
-  bool SafePlayback(HDC hdc) const override;
-};
-
 // Class for converting PDF to another format for printing (Emf, Postscript).
 // Class lives on the UI thread.
 // Internal workflow is following:
@@ -187,23 +171,6 @@
   return metafile;
 }
 
-bool PostScriptMetaFile::SafePlayback(HDC hdc) const {
-  Emf::Enumerator emf_enum(*this, nullptr, nullptr);
-  for (const Emf::Record& record : emf_enum) {
-    auto* emf_record = record.record();
-    if (emf_record->iType != EMR_GDICOMMENT)
-      continue;
-
-    const EMRGDICOMMENT* comment =
-        reinterpret_cast<const EMRGDICOMMENT*>(emf_record);
-    const char* data = reinterpret_cast<const char*>(comment->Data);
-    const uint16_t* ptr = reinterpret_cast<const uint16_t*>(data);
-    int ret = ExtEscape(hdc, PASSTHROUGH, 2 + *ptr, data, 0, nullptr);
-    DCHECK_EQ(*ptr, ret);
-  }
-  return true;
-}
-
 PdfConverterImpl::PdfConverterImpl(scoped_refptr<base::RefCountedMemory> data,
                                    const PdfRenderSettings& settings,
                                    const std::optional<bool>& use_skia,
diff --git a/chrome/browser/printing/system_access_process_print_browsertest.cc b/chrome/browser/printing/system_access_process_print_browsertest.cc
index 7205939..8605f09 100644
--- a/chrome/browser/printing/system_access_process_print_browsertest.cc
+++ b/chrome/browser/printing/system_access_process_print_browsertest.cc
@@ -1562,31 +1562,6 @@
   ASSERT_TRUE(web_contents);
   SetUpPrintViewManager(web_contents);
 
-#if BUILDFLAG(IS_WIN)
-  if (UseLanguageType() == mojom::PrinterLanguageType::kNone) {
-    // The expected events for this are:
-    // 1.  Update print settings.
-    // 2.  A print job is started.
-    // 3.  Rendering for 1 page of document of content.
-    // 4.  Completes with document done.
-    // 5.  Wait for the one print job to be destroyed, to ensure printing
-    //     finished cleanly before completing the test.
-    SetNumExpectedMessages(/*num=*/5);
-  } else {
-    // TODO(crbug.com/41492268):  Change to match the block above (language
-    // equals `kNone`) once the correct variation of EMF type is properly
-    // passed through to the Print Backend service.
-    // The expected events for this are:
-    // 1.  Update print settings.
-    // 2.  A print job is started.
-    // 3.  Rendering for 1 page of document of content, which fails.
-    // 4.  The print jobs is canceled.
-    // 5.  An error dialog is shown.
-    // 6.  Wait for the one print job to be destroyed, to ensure printing
-    //     finished cleanly before completing the test.
-    SetNumExpectedMessages(/*num=*/6);
-  }
-#else
   // The expected events for this are:
   // 1.  Update print settings.
   // 2.  A print job is started.
@@ -1595,33 +1570,20 @@
   // 5.  Wait for the one print job to be destroyed, to ensure printing
   //     finished cleanly before completing the test.
   SetNumExpectedMessages(/*num=*/5);
-#endif  // BUILDFLAG(IS_WIN)
   PrintAfterPreviewIsReadyAndLoaded();
 
   EXPECT_EQ(start_printing_result(), mojom::ResultCode::kSuccess);
 #if BUILDFLAG(IS_WIN)
   // TODO(crbug.com/1008222)  Include Windows coverage of
   // RenderPrintedDocument() once XPS print pipeline is added.
-  if (UseLanguageType() == mojom::PrinterLanguageType::kNone) {
-    EXPECT_EQ(render_printed_page_result(), mojom::ResultCode::kSuccess);
-    EXPECT_EQ(render_printed_page_count(), 1);
-    EXPECT_EQ(document_done_result(), mojom::ResultCode::kSuccess);
-    EXPECT_THAT(document_done_job_id(), testing::Optional(kJobId));
-    EXPECT_EQ(error_dialog_shown_count(), 0u);
-  } else {
-    // TODO(crbug.com/41492268):  Update for no failures once the correct
-    // variation of EMF type is properly passed through to the Print Backend
-    // service.
-    EXPECT_EQ(render_printed_page_result(), mojom::ResultCode::kFailed);
-    EXPECT_EQ(document_done_result(), mojom::ResultCode::kFailed);
-    EXPECT_EQ(error_dialog_shown_count(), 1u);
-  }
+  EXPECT_EQ(render_printed_page_result(), mojom::ResultCode::kSuccess);
+  EXPECT_EQ(render_printed_page_count(), 1);
 #else
   EXPECT_EQ(render_printed_document_result(), mojom::ResultCode::kSuccess);
+#endif
   EXPECT_EQ(document_done_result(), mojom::ResultCode::kSuccess);
   EXPECT_THAT(document_done_job_id(), testing::Optional(kJobId));
   EXPECT_EQ(error_dialog_shown_count(), 0u);
-#endif
   EXPECT_EQ(print_job_destruction_count(), 1);
 
 #if BUILDFLAG(IS_LINUX) && BUILDFLAG(USE_CUPS)
diff --git a/chrome/services/printing/print_backend_service_impl.cc b/chrome/services/printing/print_backend_service_impl.cc
index 167e06ad..6cea13ff 100644
--- a/chrome/services/printing/print_backend_service_impl.cc
+++ b/chrome/services/printing/print_backend_service_impl.cc
@@ -118,8 +118,9 @@
       return std::make_unique<MetafileSkia>();
 #if BUILDFLAG(IS_WIN)
     case mojom::MetafileDataType::kEMF:
-    case mojom::MetafileDataType::kPostScriptEmf:
       return std::make_unique<Emf>();
+    case mojom::MetafileDataType::kPostScriptEmf:
+      return std::make_unique<PostScriptMetaFile>();
 #endif
   }
 }
diff --git a/printing/emf_win.cc b/printing/emf_win.cc
index da97ff4..6541479 100644
--- a/printing/emf_win.cc
+++ b/printing/emf_win.cc
@@ -185,6 +185,31 @@
   return 1;
 }
 
+PostScriptMetaFile::PostScriptMetaFile() = default;
+
+PostScriptMetaFile::~PostScriptMetaFile() = default;
+
+mojom::MetafileDataType PostScriptMetaFile::GetDataType() const {
+  return mojom::MetafileDataType::kPostScriptEmf;
+}
+
+bool PostScriptMetaFile::SafePlayback(HDC hdc) const {
+  Emf::Enumerator emf_enum(*this, nullptr, nullptr);
+  for (const Emf::Record& record : emf_enum) {
+    auto* emf_record = record.record();
+    if (emf_record->iType != EMR_GDICOMMENT) {
+      continue;
+    }
+
+    auto* comment = reinterpret_cast<const EMRGDICOMMENT*>(emf_record);
+    const char* data = reinterpret_cast<const char*>(comment->Data);
+    const uint16_t* ptr = reinterpret_cast<const uint16_t*>(data);
+    int ret = ExtEscape(hdc, PASSTHROUGH, 2 + *ptr, data, 0, nullptr);
+    DCHECK_EQ(*ptr, ret);
+  }
+  return true;
+}
+
 Emf::EnumerationContext::EnumerationContext() {
   memset(this, 0, sizeof(*this));
 }
diff --git a/printing/emf_win.h b/printing/emf_win.h
index 56b2e5b6..f4cd909 100644
--- a/printing/emf_win.h
+++ b/printing/emf_win.h
@@ -102,6 +102,22 @@
   HDC hdc_;
 };
 
+// Emf subclass that knows how to play back PostScript data embedded as EMF
+// comment records.
+class COMPONENT_EXPORT(PRINTING_METAFILE) PostScriptMetaFile : public Emf {
+ public:
+  PostScriptMetaFile();
+
+  PostScriptMetaFile(const PostScriptMetaFile&) = delete;
+  PostScriptMetaFile& operator=(const PostScriptMetaFile&) = delete;
+
+  ~PostScriptMetaFile() override;
+
+  // `Emf` overrides:
+  mojom::MetafileDataType GetDataType() const override;
+  bool SafePlayback(HDC hdc) const override;
+};
+
 struct Emf::EnumerationContext {
   EnumerationContext();