[go: nahoru, domu]

Serialize LayoutOptions to DocumentDimensions

Add ToVar() and FromVar() methods to DocumentLayout::Options, allowing
serialization to and from a pp::Var. This serialization is then used to
pass layout options (such as default page orientation) to and from
JavaScript (via the "documentDimensions" message).

pp::Var is non-trivial to unit test, due to dependencies on the
browser's PPAPI interfaces. Instead, this change adds 2 browser_tests,
PDFExtensionTest.Layout3 and PDFExtensionTest.Layout4. Each runs the
same layout_test.js suite over two slightly different test PDF files,
test-layout3.pdf (with 3 pages) and test-layout4.pdf (with 4 pages).

There's currently no coverage of deserialization, as we're not doing
anything with the layout options sent back from JavaScript yet. We'll
start using FromVar() in an upcoming CL (such as crrev.com/c/1747170).

Bug: 885110
Change-Id: I8c93b74062576ee07445070e0b4a82f0f861a82e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1830398
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: K Moon <kmoon@chromium.org>
Auto-Submit: K Moon <kmoon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702324}
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 807f8c48..ff6304da 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -626,6 +626,14 @@
   RunTestsInFile("viewport_test.js", "test.pdf");
 }
 
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, Layout3) {
+  RunTestsInFile("layout_test.js", "test-layout3.pdf");
+}
+
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, Layout4) {
+  RunTestsInFile("layout_test.js", "test-layout4.pdf");
+}
+
 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, Bookmark) {
   RunTestsInFile("bookmarks_test.js", "test-bookmarks.pdf");
 }
diff --git a/chrome/test/data/pdf/layout_test.js b/chrome/test/data/pdf/layout_test.js
new file mode 100644
index 0000000..ddbc0e7
--- /dev/null
+++ b/chrome/test/data/pdf/layout_test.js
@@ -0,0 +1,51 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Tests common to all PDFs.
+const tests = [
+  function testLayoutOptions() {
+    chrome.test.assertEq(
+        {
+          defaultPageOrientation: 0,
+        },
+        viewer.viewport.getLayoutOptions());
+    chrome.test.succeed();
+  },
+];
+
+// Tests specific to each PDF's layout.
+const perLayoutTests = {
+  'test-layout3.pdf': [
+    function testDimensions3() {
+      chrome.test.assertEq(
+          {
+            width: 103,
+            height: 437,
+          },
+          viewer.viewport.getDocumentDimensions());
+      chrome.test.succeed();
+    },
+  ],
+
+  'test-layout4.pdf': [
+    function testDimensions4() {
+      chrome.test.assertEq(
+          {
+            width: 143,
+            height: 504,
+          },
+          viewer.viewport.getDocumentDimensions());
+      chrome.test.succeed();
+    },
+  ],
+};
+
+const scriptingAPI = new PDFScriptingAPI(window, window);
+scriptingAPI.setLoadCallback((success) => {
+  if (success && document.title in perLayoutTests) {
+    chrome.test.runTests(tests.concat(perLayoutTests[document.title]));
+  } else {
+    chrome.test.fail(document.title);
+  }
+});
diff --git a/chrome/test/data/pdf/test-layout3.in b/chrome/test/data/pdf/test-layout3.in
new file mode 100644
index 0000000..47932f42
--- /dev/null
+++ b/chrome/test/data/pdf/test-layout3.in
@@ -0,0 +1,49 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [ 0 0 70 100 ]
+  /Count 3
+  /Kids [ 3 0 R 4 0 R 5 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 6 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 6 0 R
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 6 0 R
+>>
+endobj
+% An asymmetrical "F" figure.
+{{object 6 0}} <<
+  {{streamlen}}
+>>
+stream
+2 0 0 2 10 25 cm
+0.0 G 0.5 g
+5 0 m
+5 25 l 20 25 l 20 20 l 10 20 l
+10 15 l 15 15 l 15 10 l 10 10 l
+10 0 l
+b
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/chrome/test/data/pdf/test-layout3.pdf b/chrome/test/data/pdf/test-layout3.pdf
new file mode 100644
index 0000000..2aa0086
--- /dev/null
+++ b/chrome/test/data/pdf/test-layout3.pdf
@@ -0,0 +1,62 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /MediaBox [ 0 0 70 100 ]
+  /Count 3
+  /Kids [ 3 0 R 4 0 R 5 0 R ]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 6 0 R
+>>
+endobj
+4 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 6 0 R
+>>
+endobj
+5 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 6 0 R
+>>
+endobj
+% An asymmetrical "F" figure.
+6 0 obj <<
+  /Length 107
+>>
+stream
+2 0 0 2 10 25 cm
+0.0 G 0.5 g
+5 0 m
+5 25 l 20 25 l 20 20 l 10 20 l
+10 15 l 15 15 l 15 10 l 10 10 l
+10 0 l
+b
+endstream
+endobj
+xref
+0 7
+0000000000 65535 f 
+0000000015 00000 n 
+0000000068 00000 n 
+0000000172 00000 n 
+0000000241 00000 n 
+0000000310 00000 n 
+0000000409 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 7
+>>
+startxref
+568
+%%EOF
diff --git a/chrome/test/data/pdf/test-layout4.in b/chrome/test/data/pdf/test-layout4.in
new file mode 100644
index 0000000..62dc71a
--- /dev/null
+++ b/chrome/test/data/pdf/test-layout4.in
@@ -0,0 +1,59 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [ 0 0 70 100 ]
+  /Count 4
+  /Kids [ 3 0 R 4 0 R 5 0 R 6 0 R ]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Rotate 0
+  /Contents 7 0 R
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Rotate 90
+  /Contents 7 0 R
+>>
+endobj
+{{object 5 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Rotate 180
+  /Contents 7 0 R
+>>
+endobj
+{{object 6 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Rotate 270
+  /Contents 7 0 R
+>>
+endobj
+% An asymmetrical "F" figure.
+{{object 7 0}} <<
+  {{streamlen}}
+>>
+stream
+2 0 0 2 10 25 cm
+0.0 G 0.5 g
+5 0 m
+5 25 l 20 25 l 20 20 l 10 20 l
+10 15 l 15 15 l 15 10 l 10 10 l
+10 0 l
+b
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/chrome/test/data/pdf/test-layout4.pdf b/chrome/test/data/pdf/test-layout4.pdf
new file mode 100644
index 0000000..240038ec2
--- /dev/null
+++ b/chrome/test/data/pdf/test-layout4.pdf
@@ -0,0 +1,73 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /MediaBox [ 0 0 70 100 ]
+  /Count 4
+  /Kids [ 3 0 R 4 0 R 5 0 R 6 0 R ]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Rotate 0
+  /Contents 7 0 R
+>>
+endobj
+4 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Rotate 90
+  /Contents 7 0 R
+>>
+endobj
+5 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Rotate 180
+  /Contents 7 0 R
+>>
+endobj
+6 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Rotate 270
+  /Contents 7 0 R
+>>
+endobj
+% An asymmetrical "F" figure.
+7 0 obj <<
+  /Length 107
+>>
+stream
+2 0 0 2 10 25 cm
+0.0 G 0.5 g
+5 0 m
+5 25 l 20 25 l 20 20 l 10 20 l
+10 15 l 15 15 l 15 10 l 10 10 l
+10 0 l
+b
+endstream
+endobj
+xref
+0 8
+0000000000 65535 f 
+0000000015 00000 n 
+0000000068 00000 n 
+0000000178 00000 n 
+0000000259 00000 n 
+0000000341 00000 n 
+0000000424 00000 n 
+0000000537 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 8
+>>
+startxref
+696
+%%EOF
diff --git a/pdf/document_layout.cc b/pdf/document_layout.cc
index fc4c133..51064a3 100644
--- a/pdf/document_layout.cc
+++ b/pdf/document_layout.cc
@@ -7,11 +7,15 @@
 #include "base/logging.h"
 #include "ppapi/cpp/rect.h"
 #include "ppapi/cpp/size.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/cpp/var_dictionary.h"
 
 namespace chrome_pdf {
 
 namespace {
 
+constexpr char kDefaultPageOrientation[] = "defaultPageOrientation";
+
 int GetWidestPageWidth(const std::vector<pp::Size>& page_sizes) {
   int widest_page_width = 0;
   for (const auto& page_size : page_sizes) {
@@ -41,6 +45,26 @@
 
 DocumentLayout::Options::~Options() = default;
 
+pp::Var DocumentLayout::Options::ToVar() const {
+  pp::VarDictionary dictionary;
+  dictionary.Set(kDefaultPageOrientation,
+                 static_cast<int32_t>(default_page_orientation_));
+  return dictionary;
+}
+
+void DocumentLayout::Options::FromVar(const pp::Var& var) {
+  pp::VarDictionary dictionary(var);
+
+  int32_t default_page_orientation =
+      dictionary.Get(kDefaultPageOrientation).AsInt();
+  DCHECK_GE(default_page_orientation,
+            static_cast<int32_t>(PageOrientation::kOriginal));
+  DCHECK_LE(default_page_orientation,
+            static_cast<int32_t>(PageOrientation::kLast));
+  default_page_orientation_ =
+      static_cast<PageOrientation>(default_page_orientation);
+}
+
 void DocumentLayout::Options::RotatePagesClockwise() {
   default_page_orientation_ = RotateClockwise(default_page_orientation_);
 }
diff --git a/pdf/document_layout.h b/pdf/document_layout.h
index 13cc51b..f67ae58 100644
--- a/pdf/document_layout.h
+++ b/pdf/document_layout.h
@@ -14,6 +14,10 @@
 #include "ppapi/cpp/rect.h"
 #include "ppapi/cpp/size.h"
 
+namespace pp {
+class Var;
+}  // namespace pp
+
 namespace chrome_pdf {
 
 // Layout of pages within a PDF document. Pages are placed as rectangles
@@ -35,6 +39,12 @@
 
     ~Options();
 
+    // Serializes layout options to a pp::Var.
+    pp::Var ToVar() const;
+
+    // Deserializes layout options from a pp::Var.
+    void FromVar(const pp::Var& var);
+
     PageOrientation default_page_orientation() const {
       return default_page_orientation_;
     }
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index a3786a8..d4fc7bcb 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -80,6 +80,7 @@
 constexpr char kJSDocumentDimensionsType[] = "documentDimensions";
 constexpr char kJSDocumentWidth[] = "width";
 constexpr char kJSDocumentHeight[] = "height";
+constexpr char kJSLayoutOptions[] = "layoutOptions";
 constexpr char kJSPageDimensions[] = "pageDimensions";
 constexpr char kJSPageX[] = "x";
 constexpr char kJSPageY[] = "y";
@@ -1292,6 +1293,7 @@
   dimensions.Set(kType, kJSDocumentDimensionsType);
   dimensions.Set(kJSDocumentWidth, pp::Var(document_size_.width()));
   dimensions.Set(kJSDocumentHeight, pp::Var(document_size_.height()));
+  dimensions.Set(kJSLayoutOptions, layout.options().ToVar());
   pp::VarArray page_dimensions_array;
   size_t num_pages = layout.page_count();
   if (page_is_processed_.size() < num_pages)