summaryrefslogtreecommitdiff
path: root/chromium/pdf
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-12-10 16:19:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-12-10 16:01:50 +0000
commit51f6c2793adab2d864b3d2b360000ef8db1d3e92 (patch)
tree835b3b4446b012c75e80177cef9fbe6972cc7dbe /chromium/pdf
parent6036726eb981b6c4b42047513b9d3f4ac865daac (diff)
downloadqtwebengine-chromium-51f6c2793adab2d864b3d2b360000ef8db1d3e92.tar.gz
BASELINE: Update Chromium to 71.0.3578.93
Change-Id: I6a32086c33670e1b033f8b10e6bf1fd4da1d105d Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/pdf')
-rw-r--r--chromium/pdf/BUILD.gn42
-rw-r--r--chromium/pdf/chunk_stream_unittest.cc2
-rw-r--r--chromium/pdf/document_loader_impl.cc2
-rw-r--r--chromium/pdf/document_loader_impl_unittest.cc36
-rw-r--r--chromium/pdf/draw_utils.cc2
-rw-r--r--chromium/pdf/out_of_process_instance.cc229
-rw-r--r--chromium/pdf/out_of_process_instance.h5
-rw-r--r--chromium/pdf/paint_manager.cc2
-rw-r--r--chromium/pdf/pdf.cc14
-rw-r--r--chromium/pdf/pdf.h11
-rw-r--r--chromium/pdf/pdf_engine.h8
-rw-r--r--chromium/pdf/pdf_transform.cc6
-rw-r--r--chromium/pdf/pdf_transform_unittest.cc18
-rw-r--r--chromium/pdf/pdfium/DEPS1
-rw-r--r--chromium/pdf/pdfium/findtext_unittest.cc162
-rw-r--r--chromium/pdf/pdfium/fuzzers/BUILD.gn34
-rw-r--r--chromium/pdf/pdfium/fuzzers/DEPS4
-rw-r--r--chromium/pdf/pdfium/fuzzers/pdfium_fuzzer.cc19
-rw-r--r--chromium/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.cc262
-rw-r--r--chromium/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h33
-rw-r--r--chromium/pdf/pdfium/fuzzers/pdfium_xfa_fuzzer.cc28
-rw-r--r--chromium/pdf/pdfium/pdfium_engine.cc169
-rw-r--r--chromium/pdf/pdfium/pdfium_engine.h7
-rw-r--r--chromium/pdf/pdfium/pdfium_engine_exports.cc50
-rw-r--r--chromium/pdf/pdfium/pdfium_engine_exports.h7
-rw-r--r--chromium/pdf/pdfium/pdfium_engine_exports_unittest.cc33
-rw-r--r--chromium/pdf/pdfium/pdfium_mem_buffer_file_write.h1
-rw-r--r--chromium/pdf/pdfium/pdfium_page.cc20
-rw-r--r--chromium/pdf/pdfium/pdfium_page.h4
-rw-r--r--chromium/pdf/pdfium/pdfium_print.cc317
-rw-r--r--chromium/pdf/pdfium/pdfium_print.h67
-rw-r--r--chromium/pdf/pdfium/pdfium_print_unittest.cc137
-rw-r--r--chromium/pdf/pdfium/pdfium_range.cc6
-rw-r--r--chromium/pdf/pdfium/pdfium_range.h8
-rw-r--r--chromium/pdf/pdfium/pdfium_test_base.cc70
-rw-r--r--chromium/pdf/pdfium/pdfium_test_base.h47
36 files changed, 928 insertions, 935 deletions
diff --git a/chromium/pdf/BUILD.gn b/chromium/pdf/BUILD.gn
index ee973f481ac..eccebb6f9de 100644
--- a/chromium/pdf/BUILD.gn
+++ b/chromium/pdf/BUILD.gn
@@ -19,7 +19,19 @@ buildflag_header("buildflags") {
if (enable_pdf) {
pdf_engine = 0 # 0 PDFium
+ config("pdf_common_config") {
+ if (pdf_engine == 0) {
+ defines = [ "PDFIUM_PRINT_TEXT_WITH_GDI" ]
+ if (pdf_enable_xfa) {
+ defines += [ "PDF_ENABLE_XFA" ]
+ }
+
+ include_dirs = [ "//third_party/pdfium" ]
+ }
+ }
+
jumbo_static_library("pdf") {
+ configs += [ ":pdf_common_config" ]
deps = [
"//base",
"//gin",
@@ -65,9 +77,6 @@ if (enable_pdf) {
"url_loader_wrapper_impl.h",
]
- include_dirs = []
- defines = []
-
if (pdf_engine == 0) {
deps += [
"//pdf/pdfium/fuzzers",
@@ -100,17 +109,27 @@ if (enable_pdf) {
"pdfium/pdfium_unsupported_features.cc",
"pdfium/pdfium_unsupported_features.h",
]
+ }
+ }
- include_dirs += [ "//third_party/pdfium" ]
+ source_set("pdf_test_utils") {
+ testonly = true
+ sources = [
+ "test/test_client.cc",
+ "test/test_client.h",
+ "test/test_document_loader.cc",
+ "test/test_document_loader.h",
+ ]
- defines += [ "PDFIUM_PRINT_TEXT_WITH_GDI" ]
- if (pdf_enable_xfa) {
- defines += [ "PDF_ENABLE_XFA" ]
- }
- }
+ deps = [
+ ":pdf",
+ "//base",
+ ]
}
test("pdf_unittests") {
+ testonly = true
+ configs += [ ":pdf_common_config" ]
sources = [
"chunk_stream_unittest.cc",
"document_loader_impl_unittest.cc",
@@ -121,6 +140,7 @@ if (enable_pdf) {
deps = [
":pdf",
+ ":pdf_test_utils",
"//base",
"//base/test:test_support",
"//ppapi/c",
@@ -139,8 +159,10 @@ if (enable_pdf) {
sources += [
"pdfium/findtext_unittest.cc",
"pdfium/pdfium_engine_exports_unittest.cc",
+ "pdfium/pdfium_print_unittest.cc",
+ "pdfium/pdfium_test_base.cc",
+ "pdfium/pdfium_test_base.h",
]
- include_dirs = [ "//third_party/pdfium" ]
if (v8_use_external_startup_data) {
data += [
diff --git a/chromium/pdf/chunk_stream_unittest.cc b/chromium/pdf/chunk_stream_unittest.cc
index 5b9ad998606..c6b979e0566 100644
--- a/chromium/pdf/chunk_stream_unittest.cc
+++ b/chromium/pdf/chunk_stream_unittest.cc
@@ -70,7 +70,7 @@ TEST(ChunkStreamTest, FillGap) {
TEST(ChunkStreamTest, Read) {
TestChunkStream stream;
stream.set_eof_pos(25);
- const unsigned char start_value = 33;
+ constexpr unsigned char start_value = 33;
unsigned char value = start_value;
auto chunk_0 = CreateChunkData();
for (auto& it : *chunk_0) {
diff --git a/chromium/pdf/document_loader_impl.cc b/chromium/pdf/document_loader_impl.cc
index f28121815c8..53c9b1f712c 100644
--- a/chromium/pdf/document_loader_impl.cc
+++ b/chromium/pdf/document_loader_impl.cc
@@ -25,7 +25,7 @@ namespace {
// current connection (like playing a cassette tape) and do not send new range
// request (like rewind a cassette tape, and continue playing after).
// Experimentally chosen value.
-const int kChunkCloseDistance = 10;
+constexpr int kChunkCloseDistance = 10;
// Return true if the HTTP response of |loader| is a successful one and loading
// should continue. 4xx error indicate subsequent requests will fail too.
diff --git a/chromium/pdf/document_loader_impl_unittest.cc b/chromium/pdf/document_loader_impl_unittest.cc
index 0595e049503..9ae3db5df31 100644
--- a/chromium/pdf/document_loader_impl_unittest.cc
+++ b/chromium/pdf/document_loader_impl_unittest.cc
@@ -232,7 +232,7 @@ class TestClient : public DocumentLoader::Client {
partial_loader_data_.CallOpenCallback(0);
uint32_t length = partial_loader_data_.byte_range().length();
while (length > 0) {
- const uint32_t max_part_len = kDefaultRequestSize;
+ constexpr uint32_t max_part_len = kDefaultRequestSize;
const uint32_t part_len = std::min(length, max_part_len);
partial_loader_data_.CallReadCallback(part_len);
length -= part_len;
@@ -468,7 +468,7 @@ TEST_F(DocumentLoaderImplTest, CompleteWithPartial) {
}
TEST_F(DocumentLoaderImplTest, PartialRequestLastChunk) {
- const uint32_t kLastChunkSize = 300;
+ constexpr uint32_t kLastChunkSize = 300;
TestClient client;
client.SetCanUsePartialLoading();
client.full_page_loader_data()->set_content_length(kDefaultRequestSize * 20 +
@@ -539,8 +539,8 @@ TEST_F(DocumentLoaderImplTest, ClearPendingRequests) {
{
EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
- const gfx::Range range_requested(15 * kDefaultRequestSize,
- 16 * kDefaultRequestSize);
+ constexpr gfx::Range range_requested(15 * kDefaultRequestSize,
+ 16 * kDefaultRequestSize);
EXPECT_EQ(range_requested.start(),
client.partial_loader_data()->open_byte_range().start());
EXPECT_LE(range_requested.end(),
@@ -575,8 +575,8 @@ TEST_F(DocumentLoaderImplTest, ClearPendingRequests) {
// Loading should be restarted.
EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
// The first requested chunk should be processed.
- const gfx::Range range_requested(35 * kDefaultRequestSize,
- 36 * kDefaultRequestSize);
+ constexpr gfx::Range range_requested(35 * kDefaultRequestSize,
+ 36 * kDefaultRequestSize);
EXPECT_EQ(range_requested.start(),
client.partial_loader_data()->open_byte_range().start());
EXPECT_LE(range_requested.end(),
@@ -597,8 +597,8 @@ TEST_F(DocumentLoaderImplTest, ClearPendingRequests) {
// Loading should be restarted .
EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
// The first requested chunk should be processed.
- const gfx::Range range_requested(70 * kDefaultRequestSize,
- 71 * kDefaultRequestSize);
+ constexpr gfx::Range range_requested(70 * kDefaultRequestSize,
+ 71 * kDefaultRequestSize);
EXPECT_EQ(range_requested.start(),
client.partial_loader_data()->open_byte_range().start());
EXPECT_LE(range_requested.end(),
@@ -676,8 +676,8 @@ TEST_F(DocumentLoaderImplTest, RequestData) {
{
EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
- const gfx::Range range_requested(13 * kDefaultRequestSize,
- 14 * kDefaultRequestSize);
+ constexpr gfx::Range range_requested(13 * kDefaultRequestSize,
+ 14 * kDefaultRequestSize);
EXPECT_EQ(range_requested.start(),
client.partial_loader_data()->open_byte_range().start());
EXPECT_LE(range_requested.end(),
@@ -694,8 +694,8 @@ TEST_F(DocumentLoaderImplTest, RequestData) {
client.partial_loader_data()->CallReadCallback(kDefaultRequestSize);
{
EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
- const gfx::Range range_requested(26 * kDefaultRequestSize,
- 27 * kDefaultRequestSize);
+ constexpr gfx::Range range_requested(26 * kDefaultRequestSize,
+ 27 * kDefaultRequestSize);
EXPECT_EQ(range_requested.start(),
client.partial_loader_data()->open_byte_range().start());
EXPECT_LE(range_requested.end(),
@@ -711,8 +711,8 @@ TEST_F(DocumentLoaderImplTest, RequestData) {
client.partial_loader_data()->CallReadCallback(kDefaultRequestSize);
{
EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
- const gfx::Range range_requested(39 * kDefaultRequestSize,
- 40 * kDefaultRequestSize);
+ constexpr gfx::Range range_requested(39 * kDefaultRequestSize,
+ 40 * kDefaultRequestSize);
EXPECT_EQ(range_requested.start(),
client.partial_loader_data()->open_byte_range().start());
EXPECT_LE(range_requested.end(),
@@ -796,8 +796,8 @@ TEST_F(DocumentLoaderImplTest, MergePendingRequests) {
// Send initial data from FullPageLoader.
client.full_page_loader_data()->CallReadCallback(kDefaultRequestSize);
- const gfx::Range range_requested(16 * kDefaultRequestSize,
- 18 * kDefaultRequestSize);
+ constexpr gfx::Range range_requested(16 * kDefaultRequestSize,
+ 18 * kDefaultRequestSize);
EXPECT_EQ(range_requested.start(),
client.partial_loader_data()->open_byte_range().start());
EXPECT_LE(range_requested.end(),
@@ -1102,7 +1102,7 @@ TEST_F(DocumentLoaderImplTest, IgnoreDataMoreThanExpectedWithPartial) {
client.partial_loader_data()->CallOpenCallback(0);
uint32_t length = expected_length;
while (length > 0) {
- const uint32_t max_part_len = kDefaultRequestSize;
+ constexpr uint32_t max_part_len = kDefaultRequestSize;
const uint32_t part_len = std::min(length, max_part_len);
client.partial_loader_data()->CallReadCallback(part_len);
length -= part_len;
@@ -1144,7 +1144,7 @@ TEST_F(DocumentLoaderImplTest, IgnoreDataMoreThanExpectedWithPartialAtFileEnd) {
client.partial_loader_data()->CallOpenCallback(0);
uint32_t length = client.partial_loader_data()->byte_range().length();
while (length > 0) {
- const uint32_t max_part_len = kDefaultRequestSize;
+ constexpr uint32_t max_part_len = kDefaultRequestSize;
const uint32_t part_len = std::min(length, max_part_len);
client.partial_loader_data()->CallReadCallback(part_len);
length -= part_len;
diff --git a/chromium/pdf/draw_utils.cc b/chromium/pdf/draw_utils.cc
index 80782521bce..adb2ceb0782 100644
--- a/chromium/pdf/draw_utils.cc
+++ b/chromium/pdf/draw_utils.cc
@@ -55,7 +55,7 @@ ShadowMatrix::ShadowMatrix(uint32_t depth, double factor, uint32_t background)
// pv - is a rounding power factor for smoothing corners.
// pv = 2.0 will make corners completely round.
- const double pv = 4.0;
+ constexpr double pv = 4.0;
// pow_pv - cache to avoid recalculating pow(x, pv) every time.
std::vector<double> pow_pv(depth_, 0.0);
diff --git a/chromium/pdf/out_of_process_instance.cc b/chromium/pdf/out_of_process_instance.cc
index 0358d15fb45..788082cd637 100644
--- a/chromium/pdf/out_of_process_instance.cc
+++ b/chromium/pdf/out_of_process_instance.cc
@@ -12,6 +12,7 @@
#include <list>
#include <memory>
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -39,130 +40,142 @@
#include "ppapi/cpp/resource.h"
#include "ppapi/cpp/url_request_info.h"
#include "ppapi/cpp/var_array.h"
+#include "ppapi/cpp/var_array_buffer.h"
#include "ppapi/cpp/var_dictionary.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/geometry/point_f.h"
+#include "url/gurl.h"
namespace chrome_pdf {
namespace {
-const char kChromePrint[] = "chrome://print/";
-const char kChromeExtension[] =
+const base::Feature kSaveEditedPDFFormExperiment{
+ "SaveEditedPDFForm", base::FEATURE_DISABLED_BY_DEFAULT};
+
+constexpr char kChromePrint[] = "chrome://print/";
+constexpr char kChromeExtension[] =
"chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai";
// Constants used in handling postMessage() messages.
-const char kType[] = "type";
-const char kJSId[] = "id";
+constexpr char kType[] = "type";
+constexpr char kJSId[] = "id";
// Beep messge arguments. (Plugin -> Page).
-const char kJSBeepType[] = "beep";
+constexpr char kJSBeepType[] = "beep";
// Viewport message arguments. (Page -> Plugin).
-const char kJSViewportType[] = "viewport";
-const char kJSUserInitiated[] = "userInitiated";
-const char kJSXOffset[] = "xOffset";
-const char kJSYOffset[] = "yOffset";
-const char kJSZoom[] = "zoom";
-const char kJSPinchPhase[] = "pinchPhase";
+constexpr char kJSViewportType[] = "viewport";
+constexpr char kJSUserInitiated[] = "userInitiated";
+constexpr char kJSXOffset[] = "xOffset";
+constexpr char kJSYOffset[] = "yOffset";
+constexpr char kJSZoom[] = "zoom";
+constexpr char kJSPinchPhase[] = "pinchPhase";
// kJSPinchX and kJSPinchY represent the center of the pinch gesture.
-const char kJSPinchX[] = "pinchX";
-const char kJSPinchY[] = "pinchY";
+constexpr char kJSPinchX[] = "pinchX";
+constexpr char kJSPinchY[] = "pinchY";
// kJSPinchVector represents the amount of panning caused by the pinch gesture.
-const char kJSPinchVectorX[] = "pinchVectorX";
-const char kJSPinchVectorY[] = "pinchVectorY";
+constexpr char kJSPinchVectorX[] = "pinchVectorX";
+constexpr char kJSPinchVectorY[] = "pinchVectorY";
// Stop scrolling message (Page -> Plugin)
-const char kJSStopScrollingType[] = "stopScrolling";
+constexpr char kJSStopScrollingType[] = "stopScrolling";
// Document dimension arguments (Plugin -> Page).
-const char kJSDocumentDimensionsType[] = "documentDimensions";
-const char kJSDocumentWidth[] = "width";
-const char kJSDocumentHeight[] = "height";
-const char kJSPageDimensions[] = "pageDimensions";
-const char kJSPageX[] = "x";
-const char kJSPageY[] = "y";
-const char kJSPageWidth[] = "width";
-const char kJSPageHeight[] = "height";
+constexpr char kJSDocumentDimensionsType[] = "documentDimensions";
+constexpr char kJSDocumentWidth[] = "width";
+constexpr char kJSDocumentHeight[] = "height";
+constexpr char kJSPageDimensions[] = "pageDimensions";
+constexpr char kJSPageX[] = "x";
+constexpr char kJSPageY[] = "y";
+constexpr char kJSPageWidth[] = "width";
+constexpr char kJSPageHeight[] = "height";
// Document load progress arguments (Plugin -> Page)
-const char kJSLoadProgressType[] = "loadProgress";
-const char kJSProgressPercentage[] = "progress";
+constexpr char kJSLoadProgressType[] = "loadProgress";
+constexpr char kJSProgressPercentage[] = "progress";
// Document print preview loaded (Plugin -> Page)
-const char kJSPreviewLoadedType[] = "printPreviewLoaded";
+constexpr char kJSPreviewLoadedType[] = "printPreviewLoaded";
// Metadata
-const char kJSMetadataType[] = "metadata";
-const char kJSBookmarks[] = "bookmarks";
-const char kJSTitle[] = "title";
+constexpr char kJSMetadataType[] = "metadata";
+constexpr char kJSBookmarks[] = "bookmarks";
+constexpr char kJSTitle[] = "title";
// Get password (Plugin -> Page)
-const char kJSGetPasswordType[] = "getPassword";
+constexpr char kJSGetPasswordType[] = "getPassword";
// Get password complete arguments (Page -> Plugin)
-const char kJSGetPasswordCompleteType[] = "getPasswordComplete";
-const char kJSPassword[] = "password";
+constexpr char kJSGetPasswordCompleteType[] = "getPasswordComplete";
+constexpr char kJSPassword[] = "password";
// Print (Page -> Plugin)
-const char kJSPrintType[] = "print";
+constexpr char kJSPrintType[] = "print";
// Save (Page -> Plugin)
-const char kJSSaveType[] = "save";
+constexpr char kJSSaveType[] = "save";
+constexpr char kJSToken[] = "token";
+// Save Data (Plugin -> Page)
+constexpr char kJSSaveDataType[] = "saveData";
+constexpr char kJSFileName[] = "fileName";
+constexpr char kJSDataToSave[] = "dataToSave";
+// Consume save token (Plugin -> Page)
+constexpr char kJSConsumeSaveTokenType[] = "consumeSaveToken";
// Go to page (Plugin -> Page)
-const char kJSGoToPageType[] = "goToPage";
-const char kJSPageNumber[] = "page";
+constexpr char kJSGoToPageType[] = "goToPage";
+constexpr char kJSPageNumber[] = "page";
// Reset print preview mode (Page -> Plugin)
-const char kJSResetPrintPreviewModeType[] = "resetPrintPreviewMode";
-const char kJSPrintPreviewUrl[] = "url";
-const char kJSPrintPreviewGrayscale[] = "grayscale";
-const char kJSPrintPreviewPageCount[] = "pageCount";
+constexpr char kJSResetPrintPreviewModeType[] = "resetPrintPreviewMode";
+constexpr char kJSPrintPreviewUrl[] = "url";
+constexpr char kJSPrintPreviewGrayscale[] = "grayscale";
+constexpr char kJSPrintPreviewPageCount[] = "pageCount";
// Load preview page (Page -> Plugin)
-const char kJSLoadPreviewPageType[] = "loadPreviewPage";
-const char kJSPreviewPageUrl[] = "url";
-const char kJSPreviewPageIndex[] = "index";
+constexpr char kJSLoadPreviewPageType[] = "loadPreviewPage";
+constexpr char kJSPreviewPageUrl[] = "url";
+constexpr char kJSPreviewPageIndex[] = "index";
// Set scroll position (Plugin -> Page)
-const char kJSSetScrollPositionType[] = "setScrollPosition";
-const char kJSPositionX[] = "x";
-const char kJSPositionY[] = "y";
+constexpr char kJSSetScrollPositionType[] = "setScrollPosition";
+constexpr char kJSPositionX[] = "x";
+constexpr char kJSPositionY[] = "y";
// Scroll by (Plugin -> Page)
-const char kJSScrollByType[] = "scrollBy";
+constexpr char kJSScrollByType[] = "scrollBy";
// Cancel the stream URL request (Plugin -> Page)
-const char kJSCancelStreamUrlType[] = "cancelStreamUrl";
+constexpr char kJSCancelStreamUrlType[] = "cancelStreamUrl";
// Navigate to the given URL (Plugin -> Page)
-const char kJSNavigateType[] = "navigate";
-const char kJSNavigateUrl[] = "url";
-const char kJSNavigateWindowOpenDisposition[] = "disposition";
+constexpr char kJSNavigateType[] = "navigate";
+constexpr char kJSNavigateUrl[] = "url";
+constexpr char kJSNavigateWindowOpenDisposition[] = "disposition";
// Open the email editor with the given parameters (Plugin -> Page)
-const char kJSEmailType[] = "email";
-const char kJSEmailTo[] = "to";
-const char kJSEmailCc[] = "cc";
-const char kJSEmailBcc[] = "bcc";
-const char kJSEmailSubject[] = "subject";
-const char kJSEmailBody[] = "body";
+constexpr char kJSEmailType[] = "email";
+constexpr char kJSEmailTo[] = "to";
+constexpr char kJSEmailCc[] = "cc";
+constexpr char kJSEmailBcc[] = "bcc";
+constexpr char kJSEmailSubject[] = "subject";
+constexpr char kJSEmailBody[] = "body";
// Rotation (Page -> Plugin)
-const char kJSRotateClockwiseType[] = "rotateClockwise";
-const char kJSRotateCounterclockwiseType[] = "rotateCounterclockwise";
+constexpr char kJSRotateClockwiseType[] = "rotateClockwise";
+constexpr char kJSRotateCounterclockwiseType[] = "rotateCounterclockwise";
// Select all text in the document (Page -> Plugin)
-const char kJSSelectAllType[] = "selectAll";
+constexpr char kJSSelectAllType[] = "selectAll";
// Get the selected text in the document (Page -> Plugin)
-const char kJSGetSelectedTextType[] = "getSelectedText";
+constexpr char kJSGetSelectedTextType[] = "getSelectedText";
// Reply with selected text (Plugin -> Page)
-const char kJSGetSelectedTextReplyType[] = "getSelectedTextReply";
-const char kJSSelectedText[] = "selectedText";
+constexpr char kJSGetSelectedTextReplyType[] = "getSelectedTextReply";
+constexpr char kJSSelectedText[] = "selectedText";
// Get the named destination with the given name (Page -> Plugin)
-const char kJSGetNamedDestinationType[] = "getNamedDestination";
-const char kJSGetNamedDestination[] = "namedDestination";
+constexpr char kJSGetNamedDestinationType[] = "getNamedDestination";
+constexpr char kJSGetNamedDestination[] = "namedDestination";
// Reply with the page number of the named destination (Plugin -> Page)
-const char kJSGetNamedDestinationReplyType[] = "getNamedDestinationReply";
-const char kJSNamedDestinationPageNumber[] = "pageNumber";
+constexpr char kJSGetNamedDestinationReplyType[] = "getNamedDestinationReply";
+constexpr char kJSNamedDestinationPageNumber[] = "pageNumber";
-const char kJSTransformPagePointType[] = "transformPagePoint";
-const char kJSTransformPagePointReplyType[] = "transformPagePointReply";
+constexpr char kJSTransformPagePointType[] = "transformPagePoint";
+constexpr char kJSTransformPagePointReplyType[] = "transformPagePointReply";
// Selecting text in document (Plugin -> Page)
-const char kJSSetIsSelectingType[] = "setIsSelecting";
-const char kJSIsSelecting[] = "isSelecting";
-
-// Notify when the document was changed and edit mode is toggled.
-const char kJSSetIsEditModeType[] = "setIsEditMode";
-const char kJSIsEditMode[] = "isEditMode";
+constexpr char kJSSetIsSelectingType[] = "setIsSelecting";
+constexpr char kJSIsSelecting[] = "isSelecting";
// Notify when a form field is focused (Plugin -> Page)
-const char kJSFieldFocusType[] = "formFocusChange";
-const char kJSFieldFocus[] = "focused";
+constexpr char kJSFieldFocusType[] = "formFocusChange";
+constexpr char kJSFieldFocus[] = "focused";
+
+constexpr int kFindResultCooldownMs = 100;
-const int kFindResultCooldownMs = 100;
+// Do not save forms with over 100 MB. This cap should be kept in sync with and
+// is also enforced in chrome/browser/resources/pdf/pdf_viewer.js.
+constexpr size_t kMaximumSavedFileSize = 100u * 1000u * 1000u;
// Same value as printing::COMPLETE_PREVIEW_DOCUMENT_INDEX.
constexpr int kCompletePDFIndex = -1;
@@ -171,11 +184,11 @@ constexpr int kInvalidPDFIndex = -2;
// A delay to wait between each accessibility page to keep the system
// responsive.
-const int kAccessibilityPageDelayMs = 100;
+constexpr int kAccessibilityPageDelayMs = 100;
-const double kMinZoom = 0.01;
+constexpr double kMinZoom = 0.01;
-const char kPPPPdfInterface[] = PPP_PDF_INTERFACE_1;
+constexpr char kPPPPdfInterface[] = PPP_PDF_INTERFACE_1;
// Used for UMA. Do not delete entries, and keep in sync with histograms.xml.
enum PDFFeatures {
@@ -187,7 +200,7 @@ enum PDFFeatures {
// Used for UMA. Do not delete entries, and keep in sync with histograms.xml
// and pdfium/public/fpdf_annot.h.
-const int kAnnotationTypesCount = 28;
+constexpr int kAnnotationTypesCount = 28;
PP_Var GetLinkAtPosition(PP_Instance instance, PP_Point point) {
pp::Var var;
@@ -651,9 +664,8 @@ void OutOfProcessInstance::HandleMessage(const pp::Var& message) {
}
} else if (type == kJSPrintType) {
Print();
- } else if (type == kJSSaveType) {
- engine_->KillFormFocus();
- pp::PDF::SaveAs(this);
+ } else if (type == kJSSaveType && dict.Get(pp::Var(kJSToken)).is_string()) {
+ Save(dict.Get(pp::Var(kJSToken)).AsString());
} else if (type == kJSRotateClockwiseType) {
RotateClockwise();
} else if (type == kJSRotateCounterclockwiseType) {
@@ -1461,6 +1473,44 @@ void OutOfProcessInstance::GetDocumentPassword(
PostMessage(message);
}
+void OutOfProcessInstance::Save(const std::string& token) {
+ engine_->KillFormFocus();
+
+ if (!base::FeatureList::IsEnabled(kSaveEditedPDFFormExperiment) ||
+ !edit_mode_) {
+ ConsumeSaveToken(token);
+ pp::PDF::SaveAs(this);
+ return;
+ }
+
+ GURL url(url_);
+ std::string file_name = url.ExtractFileName();
+ file_name = net::UnescapeURLComponent(file_name, net::UnescapeRule::SPACES);
+ std::vector<uint8_t> data = engine_->GetSaveData();
+
+ if (data.size() == 0u || data.size() > kMaximumSavedFileSize) {
+ // TODO(thestig): Add feedback to the user that a failure occurred.
+ ConsumeSaveToken(token);
+ return;
+ }
+
+ pp::VarDictionary message;
+ message.Set(kType, kJSSaveDataType);
+ message.Set(kJSToken, pp::Var(token));
+ message.Set(kJSFileName, pp::Var(file_name));
+ pp::VarArrayBuffer buffer(data.size());
+ std::copy(data.begin(), data.end(), reinterpret_cast<char*>(buffer.Map()));
+ message.Set(kJSDataToSave, buffer);
+ PostMessage(message);
+}
+
+void OutOfProcessInstance::ConsumeSaveToken(const std::string& token) {
+ pp::VarDictionary message;
+ message.Set(kType, kJSConsumeSaveTokenType);
+ message.Set(kJSToken, pp::Var(token));
+ PostMessage(message);
+}
+
void OutOfProcessInstance::Beep() {
pp::VarDictionary message;
message.Set(pp::Var(kType), pp::Var(kJSBeepType));
@@ -1652,7 +1702,7 @@ void OutOfProcessInstance::DocumentLoadComplete(
}
pp::PDF::SetContentRestriction(this, content_restrictions);
- static const int32_t kMaxFileSizeInKB = 12 * 1024 * 1024;
+ static constexpr int32_t kMaxFileSizeInKB = 12 * 1024 * 1024;
HistogramCustomCounts("PDF.FileSizeInKB", file_size / 1024, 0,
kMaxFileSizeInKB, 50);
HistogramCustomCounts("PDF.PageCount", document_features.page_count, 1,
@@ -1898,10 +1948,7 @@ void OutOfProcessInstance::IsSelectingChanged(bool is_selecting) {
}
void OutOfProcessInstance::IsEditModeChanged(bool is_edit_mode) {
- pp::VarDictionary message;
- message.Set(kType, kJSSetIsEditModeType);
- message.Set(kJSIsEditMode, pp::Var(is_edit_mode));
- PostMessage(message);
+ edit_mode_ = is_edit_mode;
}
float OutOfProcessInstance::GetToolbarHeightInScreenCoords() {
diff --git a/chromium/pdf/out_of_process_instance.h b/chromium/pdf/out_of_process_instance.h
index 18ce4321f15..2c91f54f1d1 100644
--- a/chromium/pdf/out_of_process_instance.h
+++ b/chromium/pdf/out_of_process_instance.h
@@ -186,6 +186,9 @@ class OutOfProcessInstance : public pp::Instance,
// frame's origin.
pp::URLLoader CreateURLLoaderInternal();
+ void Save(const std::string& token);
+ void ConsumeSaveToken(const std::string& token);
+
void FormDidOpen(int32_t result);
void UserMetricsRecordAction(const std::string& action);
@@ -427,6 +430,8 @@ class OutOfProcessInstance : public pp::Instance,
// Annotation types that were already counted for this document.
std::set<int> annotation_types_counted_;
+ bool edit_mode_ = false;
+
// The current state of accessibility: either off, enabled but waiting
// for the document to load, or fully loaded.
enum AccessibilityState {
diff --git a/chromium/pdf/paint_manager.cc b/chromium/pdf/paint_manager.cc
index fdccaef481b..e83805e0e0a 100644
--- a/chromium/pdf/paint_manager.cc
+++ b/chromium/pdf/paint_manager.cc
@@ -55,7 +55,7 @@ pp::Size PaintManager::GetNewContextSize(const pp::Size& current_context_size,
const pp::Size& plugin_size) {
// The amount of additional space in pixels to allocate to the right/bottom of
// the context.
- const int kBufferSize = 50;
+ constexpr int kBufferSize = 50;
// Default to returning the same size.
pp::Size result = current_context_size;
diff --git a/chromium/pdf/pdf.cc b/chromium/pdf/pdf.cc
index bfa6a4b8ad0..c45791a92b7 100644
--- a/chromium/pdf/pdf.cc
+++ b/chromium/pdf/pdf.cc
@@ -139,27 +139,29 @@ bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer,
std::vector<uint8_t> ConvertPdfPagesToNupPdf(
std::vector<base::span<const uint8_t>> input_buffers,
size_t pages_per_sheet,
- const gfx::Size& page_size) {
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) {
ScopedSdkInitializer scoped_sdk_initializer;
if (!scoped_sdk_initializer.Init())
return std::vector<uint8_t>();
PDFEngineExports* engine_exports = PDFEngineExports::Get();
- return engine_exports->ConvertPdfPagesToNupPdf(std::move(input_buffers),
- pages_per_sheet, page_size);
+ return engine_exports->ConvertPdfPagesToNupPdf(
+ std::move(input_buffers), pages_per_sheet, page_size, printable_area);
}
std::vector<uint8_t> ConvertPdfDocumentToNupPdf(
base::span<const uint8_t> input_buffer,
size_t pages_per_sheet,
- const gfx::Size& page_size) {
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) {
ScopedSdkInitializer scoped_sdk_initializer;
if (!scoped_sdk_initializer.Init())
return std::vector<uint8_t>();
PDFEngineExports* engine_exports = PDFEngineExports::Get();
- return engine_exports->ConvertPdfDocumentToNupPdf(input_buffer,
- pages_per_sheet, page_size);
+ return engine_exports->ConvertPdfDocumentToNupPdf(
+ input_buffer, pages_per_sheet, page_size, printable_area);
}
} // namespace chrome_pdf
diff --git a/chromium/pdf/pdf.h b/chromium/pdf/pdf.h
index 4617943b003..f17b7ea9839 100644
--- a/chromium/pdf/pdf.h
+++ b/chromium/pdf/pdf.h
@@ -21,6 +21,7 @@ typedef void (*PDFEnsureTypefaceCharactersAccessible)(const LOGFONT* font,
#endif
namespace gfx {
+class Rect;
class Size;
}
@@ -132,6 +133,8 @@ bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer,
// document is used.
// |pages_per_sheet| is the number of pages to put on one sheet.
// |page_size| is the output page size, measured in PDF "user space" units.
+// |printable_area| is the output page printable area, measured in PDF
+// "user space" units. Should be smaller than |page_size|.
//
// |page_size| is the print media size. The page size of the output N-up PDF is
// determined by the |pages_per_sheet|, the orientation of the PDF pages
@@ -145,13 +148,16 @@ bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer,
std::vector<uint8_t> ConvertPdfPagesToNupPdf(
std::vector<base::span<const uint8_t>> input_buffers,
size_t pages_per_sheet,
- const gfx::Size& page_size);
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area);
// Convert a PDF document to a N-up PDF document.
// |input_buffer| is the buffer that contains the entire PDF document to be
// converted to a N-up PDF document.
// |pages_per_sheet| is the number of pages to put on one sheet.
// |page_size| is the output page size, measured in PDF "user space" units.
+// |printable_area| is the output page printable area, measured in PDF
+// "user space" units. Should be smaller than |page_size|.
//
// Refer to the description of ConvertPdfPagesToNupPdf to understand how the
// output page size will be calculated.
@@ -159,7 +165,8 @@ std::vector<uint8_t> ConvertPdfPagesToNupPdf(
std::vector<uint8_t> ConvertPdfDocumentToNupPdf(
base::span<const uint8_t> input_buffer,
size_t pages_per_sheet,
- const gfx::Size& page_size);
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area);
} // namespace chrome_pdf
diff --git a/chromium/pdf/pdf_engine.h b/chromium/pdf/pdf_engine.h
index 521337eb06a..047f24611e1 100644
--- a/chromium/pdf/pdf_engine.h
+++ b/chromium/pdf/pdf_engine.h
@@ -42,6 +42,7 @@ typedef void (*PDFEnsureTypefaceCharactersAccessible)(const LOGFONT* font,
struct PP_PdfPrintSettings_Dev;
namespace gfx {
+class Rect;
class Size;
}
@@ -401,6 +402,7 @@ class PDFEngine {
virtual void AppendPage(PDFEngine* engine, int index) = 0;
virtual std::string GetMetadata(const std::string& key) = 0;
+ virtual std::vector<uint8_t> GetSaveData() = 0;
virtual void SetCaretPosition(const pp::Point& position) = 0;
virtual void MoveRangeSelectionExtent(const pp::Point& extent) = 0;
@@ -470,13 +472,15 @@ class PDFEngineExports {
virtual std::vector<uint8_t> ConvertPdfPagesToNupPdf(
std::vector<base::span<const uint8_t>> input_buffers,
size_t pages_per_sheet,
- const gfx::Size& page_size) = 0;
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) = 0;
// See the definition of ConvertPdfDocumentToNupPdf in pdf.cc for details.
virtual std::vector<uint8_t> ConvertPdfDocumentToNupPdf(
base::span<const uint8_t> input_buffer,
size_t pages_per_sheet,
- const gfx::Size& page_size) = 0;
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) = 0;
virtual bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
int* page_count,
diff --git a/chromium/pdf/pdf_transform.cc b/chromium/pdf/pdf_transform.cc
index 28a69de503f..0acb36c44bc 100644
--- a/chromium/pdf/pdf_transform.cc
+++ b/chromium/pdf/pdf_transform.cc
@@ -42,9 +42,9 @@ double CalculateScaleFactor(const gfx::Rect& content_rect,
}
void SetDefaultClipBox(bool rotated, PdfRectangle* clip_box) {
- const int kDpi = 72;
- const float kPaperWidth = 8.5 * kDpi;
- const float kPaperHeight = 11 * kDpi;
+ constexpr int kDpi = 72;
+ constexpr float kPaperWidth = 8.5 * kDpi;
+ constexpr float kPaperHeight = 11 * kDpi;
clip_box->left = 0;
clip_box->bottom = 0;
clip_box->right = rotated ? kPaperHeight : kPaperWidth;
diff --git a/chromium/pdf/pdf_transform_unittest.cc b/chromium/pdf/pdf_transform_unittest.cc
index e52b02a8665..faf424e8c9b 100644
--- a/chromium/pdf/pdf_transform_unittest.cc
+++ b/chromium/pdf/pdf_transform_unittest.cc
@@ -12,10 +12,10 @@ namespace chrome_pdf {
namespace {
-const float kDefaultWidth = 8.5 * printing::kPointsPerInch;
-const float kDefaultHeight = 11.0 * printing::kPointsPerInch;
-const float kDefaultRatio = kDefaultWidth / kDefaultHeight;
-const double kTolerance = 0.0001;
+constexpr float kDefaultWidth = 8.5 * printing::kPointsPerInch;
+constexpr float kDefaultHeight = 11.0 * printing::kPointsPerInch;
+constexpr float kDefaultRatio = kDefaultWidth / kDefaultHeight;
+constexpr double kTolerance = 0.0001;
void ExpectDefaultPortraitBox(const PdfRectangle& box) {
EXPECT_FLOAT_EQ(0, box.left);
@@ -130,7 +130,7 @@ TEST(PdfTransformTest, CalculateMediaBoxAndCropBox) {
ExpectDefaultLandscapeBox(crop_box);
// Assume crop box is missing.
- const PdfRectangle expected_box = {0, 0, 42, 420};
+ constexpr PdfRectangle expected_box = {0, 0, 42, 420};
media_box = expected_box;
InitializeBoxToInvalidValues(&crop_box);
CalculateMediaBoxAndCropBox(false, true, false, &media_box, &crop_box);
@@ -188,7 +188,7 @@ TEST(PdfTransformTest, CalculateClipBoxBoundary) {
}
TEST(PdfTransformTest, CalculateScaledClipBoxOffset) {
- const gfx::Rect rect(kDefaultWidth, kDefaultHeight);
+ constexpr gfx::Rect rect(kDefaultWidth, kDefaultHeight);
PdfRectangle clip_box;
double offset_x;
double offset_y;
@@ -210,7 +210,7 @@ TEST(PdfTransformTest, CalculateScaledClipBoxOffset) {
TEST(PdfTransformTest, CalculateNonScaledClipBoxOffset) {
int page_width = kDefaultWidth;
int page_height = kDefaultHeight;
- const gfx::Rect rect(kDefaultWidth, kDefaultHeight);
+ constexpr gfx::Rect rect(kDefaultWidth, kDefaultHeight);
PdfRectangle clip_box;
double offset_x;
double offset_y;
@@ -280,12 +280,12 @@ TEST(PdfTransformTest, CalculateNonScaledClipBoxOffset) {
TEST(PdfTransformTest, ReversedMediaBox) {
int page_width = kDefaultWidth;
int page_height = kDefaultHeight;
- const gfx::Rect rect(kDefaultWidth, kDefaultHeight);
+ constexpr gfx::Rect rect(kDefaultWidth, kDefaultHeight);
PdfRectangle clip_box;
double offset_x;
double offset_y;
- const PdfRectangle expected_media_box_b491160 = {0, -792, 612, 0};
+ constexpr PdfRectangle expected_media_box_b491160 = {0, -792, 612, 0};
PdfRectangle media_box_b491160 = {0, 0, 612, -792};
CalculateMediaBoxAndCropBox(false, true, false, &media_box_b491160,
&clip_box);
diff --git a/chromium/pdf/pdfium/DEPS b/chromium/pdf/pdfium/DEPS
index f157a81c75d..e8058f09b8a 100644
--- a/chromium/pdf/pdfium/DEPS
+++ b/chromium/pdf/pdfium/DEPS
@@ -3,6 +3,7 @@ include_rules = [
"+gin/public",
"+gin/v8_initializer.h",
"+printing/nup_parameters.h",
+ "+printing/page_setup.h",
"+third_party/pdfium/public",
"+ui/gfx/codec/jpeg_codec.h",
]
diff --git a/chromium/pdf/pdfium/findtext_unittest.cc b/chromium/pdf/pdfium/findtext_unittest.cc
index c077b748515..895fc39d66a 100644
--- a/chromium/pdf/pdfium/findtext_unittest.cc
+++ b/chromium/pdf/pdfium/findtext_unittest.cc
@@ -2,14 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/files/file_util.h"
#include "base/optional.h"
-#include "base/path_service.h"
-#include "pdf/document_loader.h"
#include "pdf/pdfium/pdfium_engine.h"
-#include "pdf/url_loader_wrapper.h"
+#include "pdf/pdfium/pdfium_test_base.h"
+#include "pdf/test/test_client.h"
#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
using testing::InSequence;
using testing::_;
@@ -18,79 +15,15 @@ namespace chrome_pdf {
namespace {
-class TestDocumentLoader : public DocumentLoader {
+class FindTextTestClient : public TestClient {
public:
- explicit TestDocumentLoader(Client* client) : client_(client) {
- base::FilePath pdf_path;
- CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &pdf_path));
- pdf_path = pdf_path.Append(FILE_PATH_LITERAL("pdf"))
- .Append(FILE_PATH_LITERAL("test"))
- .Append(FILE_PATH_LITERAL("data"))
- .Append(FILE_PATH_LITERAL("hello_world2.pdf"));
- CHECK(base::ReadFileToString(pdf_path, &pdf_data_));
- }
- ~TestDocumentLoader() override = default;
-
- // DocumentLoader:
- bool Init(std::unique_ptr<URLLoaderWrapper> loader,
- const std::string& url) override {
- NOTREACHED();
- return false;
- }
-
- bool GetBlock(uint32_t position, uint32_t size, void* buf) const override {
- if (!IsDataAvailable(position, size))
- return false;
-
- memcpy(buf, pdf_data_.data() + position, size);
- return true;
- }
-
- bool IsDataAvailable(uint32_t position, uint32_t size) const override {
- return position < pdf_data_.size() && size <= pdf_data_.size() &&
- position + size <= pdf_data_.size();
- }
-
- void RequestData(uint32_t position, uint32_t size) override {
- client_->OnDocumentComplete();
- }
-
- bool IsDocumentComplete() const override { return true; }
-
- uint32_t GetDocumentSize() const override { return pdf_data_.size(); }
-
- uint32_t BytesReceived() const override { return pdf_data_.size(); }
-
- private:
- Client* const client_;
- std::string pdf_data_;
-};
-
-std::unique_ptr<DocumentLoader> CreateTestDocumentLoader(
- DocumentLoader::Client* client) {
- return std::make_unique<TestDocumentLoader>(client);
-}
-
-class TestClient : public PDFEngine::Client {
- public:
- TestClient() = default;
- ~TestClient() override = default;
+ FindTextTestClient() = default;
+ ~FindTextTestClient() override = default;
// PDFEngine::Client:
MOCK_METHOD2(NotifyNumberOfFindResultsChanged, void(int, bool));
MOCK_METHOD1(NotifySelectedFindResultChanged, void((int)));
- bool Confirm(const std::string& message) override { return false; }
-
- std::string Prompt(const std::string& question,
- const std::string& default_answer) override {
- return std::string();
- }
-
- std::string GetURL() override { return std::string(); }
-
- pp::URLLoader CreateURLLoader() override { return pp::URLLoader(); }
-
std::vector<SearchStringResult> SearchString(const base::char16* string,
const base::char16* term,
bool case_sensitive) override {
@@ -115,54 +48,19 @@ class TestClient : public PDFEngine::Client {
return results;
}
- pp::Instance* GetPluginInstance() override { return nullptr; }
-
- bool IsPrintPreview() override { return false; }
-
- uint32_t GetBackgroundColor() override { return 0; }
-
- float GetToolbarHeightInScreenCoords() override { return 0; }
-
private:
- DISALLOW_COPY_AND_ASSIGN(TestClient);
+ DISALLOW_COPY_AND_ASSIGN(FindTextTestClient);
};
} // namespace
-class FindTextTest : public testing::Test {
- public:
- FindTextTest() = default;
- ~FindTextTest() override = default;
-
- protected:
- void SetUp() override {
- InitializePDFium();
- PDFiumEngine::SetCreateDocumentLoaderFunctionForTesting(
- &CreateTestDocumentLoader);
- }
- void TearDown() override {
- PDFiumEngine::SetCreateDocumentLoaderFunctionForTesting(nullptr);
- FPDF_DestroyLibrary();
- }
-
- void InitializePDFium() {
- FPDF_LIBRARY_CONFIG config;
- config.version = 2;
- config.m_pUserFontPaths = nullptr;
- config.m_pIsolate = nullptr;
- config.m_v8EmbedderSlot = 0;
- FPDF_InitLibraryWithConfig(&config);
- }
-
- DISALLOW_COPY_AND_ASSIGN(FindTextTest);
-};
+using FindTextTest = PDFiumTestBase;
TEST_F(FindTextTest, FindText) {
- pp::URLLoader dummy_loader;
- TestClient client;
- PDFiumEngine engine(&client, true);
- ASSERT_TRUE(engine.New("https://chromium.org/dummy.pdf", ""));
- ASSERT_TRUE(engine.HandleDocumentLoad(dummy_loader));
+ FindTextTestClient client;
+ std::unique_ptr<PDFiumEngine> engine =
+ InitializeEngine(&client, FILE_PATH_LITERAL("hello_world2.pdf"));
+ ASSERT_TRUE(engine);
{
InSequence sequence;
@@ -174,7 +72,43 @@ TEST_F(FindTextTest, FindText) {
EXPECT_CALL(client, NotifyNumberOfFindResultsChanged(10, true));
}
- engine.StartFind("o", /*case_sensitive=*/true);
+ engine->StartFind("o", /*case_sensitive=*/true);
+}
+
+TEST_F(FindTextTest, FindHyphenatedText) {
+ FindTextTestClient client;
+ std::unique_ptr<PDFiumEngine> engine =
+ InitializeEngine(&client, FILE_PATH_LITERAL("spanner.pdf"));
+ ASSERT_TRUE(engine);
+
+ {
+ InSequence sequence;
+
+ EXPECT_CALL(client, NotifyNumberOfFindResultsChanged(1, false));
+ EXPECT_CALL(client, NotifySelectedFindResultChanged(0));
+ for (int i = 1; i < 6; ++i)
+ EXPECT_CALL(client, NotifyNumberOfFindResultsChanged(i + 1, false));
+ EXPECT_CALL(client, NotifyNumberOfFindResultsChanged(6, true));
+ }
+
+ engine->StartFind("application", /*case_sensitive=*/true);
+}
+
+TEST_F(FindTextTest, FindLineBreakText) {
+ FindTextTestClient client;
+ std::unique_ptr<PDFiumEngine> engine =
+ InitializeEngine(&client, FILE_PATH_LITERAL("spanner.pdf"));
+ ASSERT_TRUE(engine);
+
+ {
+ InSequence sequence;
+
+ EXPECT_CALL(client, NotifyNumberOfFindResultsChanged(1, false));
+ EXPECT_CALL(client, NotifySelectedFindResultChanged(0));
+ EXPECT_CALL(client, NotifyNumberOfFindResultsChanged(1, true));
+ }
+
+ engine->StartFind("is the first system", /*case_sensitive=*/true);
}
} // namespace chrome_pdf
diff --git a/chromium/pdf/pdfium/fuzzers/BUILD.gn b/chromium/pdf/pdfium/fuzzers/BUILD.gn
index ffac41d48fc..124139ea78b 100644
--- a/chromium/pdf/pdfium/fuzzers/BUILD.gn
+++ b/chromium/pdf/pdfium/fuzzers/BUILD.gn
@@ -59,23 +59,16 @@ group("pdf_fuzzers") {
}
fuzzer_test("pdfium_fuzzer") {
- sources = [
- "pdfium_fuzzer.cc",
- "pdfium_fuzzer_helper.cc",
- "pdfium_fuzzer_helper.h",
- ]
+ sources = []
deps = [
- "//third_party/pdfium",
- "//third_party/pdfium:test_support",
- "//v8",
- "//v8:v8_libplatform",
- ]
- additional_configs = [
- "//third_party/pdfium:pdfium_core_config",
- "//v8:external_startup_data",
+ "//third_party/pdfium/testing/fuzzers:pdfium_fuzzer_src",
]
dict = "dicts/pdf.dict"
seed_corpus = "//third_party/pdfium/testing/resources"
+ deps += [
+ "//third_party/pdfium",
+ "//third_party/pdfium:test_support",
+ ]
}
fuzzer_test("pdf_cmap_fuzzer") {
@@ -271,20 +264,9 @@ if (pdf_enable_xfa) {
}
fuzzer_test("pdfium_xfa_fuzzer") {
- sources = [
- "pdfium_fuzzer_helper.cc",
- "pdfium_fuzzer_helper.h",
- "pdfium_xfa_fuzzer.cc",
- ]
+ sources = []
deps = [
- "//third_party/pdfium",
- "//third_party/pdfium:test_support",
- "//v8",
- "//v8:v8_libplatform",
- ]
- additional_configs = [
- "//third_party/pdfium:pdfium_core_config",
- "//v8:external_startup_data",
+ "//third_party/pdfium/testing/fuzzers:pdfium_xfa_fuzzer_src",
]
dict = "dicts/pdf.dict"
seed_corpus = "//third_party/pdfium/testing/resources"
diff --git a/chromium/pdf/pdfium/fuzzers/DEPS b/chromium/pdf/pdfium/fuzzers/DEPS
deleted file mode 100644
index aca641cc4dd..00000000000
--- a/chromium/pdf/pdfium/fuzzers/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+third_party/pdfium/testing/test_support.h",
- "+v8/include/v8-platform.h",
-]
diff --git a/chromium/pdf/pdfium/fuzzers/pdfium_fuzzer.cc b/chromium/pdf/pdfium/fuzzers/pdfium_fuzzer.cc
deleted file mode 100644
index 1e8d9c21082..00000000000
--- a/chromium/pdf/pdfium/fuzzers/pdfium_fuzzer.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 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.
-
-#include "pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h"
-
-class PDFiumFuzzer : public PDFiumFuzzerHelper {
- public:
- PDFiumFuzzer() : PDFiumFuzzerHelper() {}
- ~PDFiumFuzzer() override = default;
-
- int GetFormCallbackVersion() const override { return 1; }
-};
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- PDFiumFuzzer fuzzer;
- fuzzer.RenderPdf(reinterpret_cast<const char*>(data), size);
- return 0;
-}
diff --git a/chromium/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.cc b/chromium/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.cc
deleted file mode 100644
index ac704de2ffc..00000000000
--- a/chromium/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.cc
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2017 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.
-
-// This fuzzer is simplified & cleaned up pdfium/samples/pdfium_test.cc
-
-#include "pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h"
-
-#include <assert.h>
-#include <limits.h>
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef _WIN32
-#include <Windows.h>
-#elif defined(__APPLE__)
-#include <mach-o/dyld.h>
-#else // Linux
-#include <unistd.h>
-#endif // _WIN32
-
-#include <memory>
-#include <sstream>
-#include <string>
-#include <utility>
-
-#include "base/memory/free_deleter.h"
-#include "third_party/pdfium/public/cpp/fpdf_scopers.h"
-#include "third_party/pdfium/public/fpdf_dataavail.h"
-#include "third_party/pdfium/public/fpdf_text.h"
-#include "third_party/pdfium/testing/test_support.h"
-#include "v8/include/v8-platform.h"
-
-namespace {
-
-int ExampleAppAlert(IPDF_JSPLATFORM*,
- FPDF_WIDESTRING,
- FPDF_WIDESTRING,
- int,
- int) {
- return 0;
-}
-
-int ExampleAppResponse(IPDF_JSPLATFORM*,
- FPDF_WIDESTRING question,
- FPDF_WIDESTRING title,
- FPDF_WIDESTRING default_value,
- FPDF_WIDESTRING label,
- FPDF_BOOL is_password,
- void* response,
- int length) {
- // UTF-16, always LE regardless of platform.
- uint8_t* ptr = static_cast<uint8_t*>(response);
- ptr[0] = 'N';
- ptr[1] = 0;
- ptr[2] = 'o';
- ptr[3] = 0;
- return 4;
-}
-
-void ExampleDocGotoPage(IPDF_JSPLATFORM*, int pageNumber) {}
-
-void ExampleDocMail(IPDF_JSPLATFORM*,
- void* mailData,
- int length,
- FPDF_BOOL UI,
- FPDF_WIDESTRING To,
- FPDF_WIDESTRING Subject,
- FPDF_WIDESTRING CC,
- FPDF_WIDESTRING BCC,
- FPDF_WIDESTRING Msg) {}
-
-void ExampleUnsupportedHandler(UNSUPPORT_INFO*, int type) {}
-
-FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
- return true;
-}
-
-void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {}
-
-std::string ProgramPath() {
- std::string result;
-
-#ifdef _WIN32
- wchar_t wpath[MAX_PATH];
- char path[MAX_PATH];
- DWORD len = GetModuleFileNameA(NULL, path, MAX_PATH);
- if (len != 0)
- result = std::string(path, len);
-#elif defined(__APPLE__)
- char path[PATH_MAX];
- unsigned int len = PATH_MAX;
- if (!_NSGetExecutablePath(path, &len)) {
- std::unique_ptr<char, base::FreeDeleter> resolved_path(
- realpath(path, nullptr));
- if (resolved_path.get())
- result = std::string(resolved_path.get());
- }
-#else // Linux
- char path[PATH_MAX];
- ssize_t len = readlink("/proc/self/exe", path, PATH_MAX);
- if (len > 0)
- result = std::string(path, len);
-#endif
- return result;
-}
-
-} // namespace
-
-PDFiumFuzzerHelper::PDFiumFuzzerHelper() = default;
-
-PDFiumFuzzerHelper::~PDFiumFuzzerHelper() = default;
-
-bool PDFiumFuzzerHelper::OnFormFillEnvLoaded(FPDF_DOCUMENT doc) {
- return true;
-}
-
-void PDFiumFuzzerHelper::RenderPdf(const char* pBuf, size_t len) {
- IPDF_JSPLATFORM platform_callbacks;
- memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
- platform_callbacks.version = 3;
- platform_callbacks.app_alert = ExampleAppAlert;
- platform_callbacks.app_response = ExampleAppResponse;
- platform_callbacks.Doc_gotoPage = ExampleDocGotoPage;
- platform_callbacks.Doc_mail = ExampleDocMail;
-
- FPDF_FORMFILLINFO form_callbacks;
- memset(&form_callbacks, '\0', sizeof(form_callbacks));
- form_callbacks.version = GetFormCallbackVersion();
- form_callbacks.m_pJsPlatform = &platform_callbacks;
-
- TestLoader loader(pBuf, len);
- FPDF_FILEACCESS file_access;
- memset(&file_access, '\0', sizeof(file_access));
- file_access.m_FileLen = static_cast<unsigned long>(len);
- file_access.m_GetBlock = TestLoader::GetBlock;
- file_access.m_Param = &loader;
-
- FX_FILEAVAIL file_avail;
- memset(&file_avail, '\0', sizeof(file_avail));
- file_avail.version = 1;
- file_avail.IsDataAvail = Is_Data_Avail;
-
- FX_DOWNLOADHINTS hints;
- memset(&hints, '\0', sizeof(hints));
- hints.version = 1;
- hints.AddSegment = Add_Segment;
-
- ScopedFPDFAvail pdf_avail(FPDFAvail_Create(&file_avail, &file_access));
-
- int nRet = PDF_DATA_NOTAVAIL;
- bool bIsLinearized = false;
- ScopedFPDFDocument doc;
- if (FPDFAvail_IsLinearized(pdf_avail.get()) == PDF_LINEARIZED) {
- doc.reset(FPDFAvail_GetDocument(pdf_avail.get(), nullptr));
- if (doc) {
- while (nRet == PDF_DATA_NOTAVAIL)
- nRet = FPDFAvail_IsDocAvail(pdf_avail.get(), &hints);
-
- if (nRet == PDF_DATA_ERROR)
- return;
-
- nRet = FPDFAvail_IsFormAvail(pdf_avail.get(), &hints);
- if (nRet == PDF_FORM_ERROR || nRet == PDF_FORM_NOTAVAIL)
- return;
-
- bIsLinearized = true;
- }
- } else {
- doc.reset(FPDF_LoadCustomDocument(&file_access, nullptr));
- }
-
- if (!doc)
- return;
-
- (void)FPDF_GetDocPermissions(doc.get());
-
- ScopedFPDFFormHandle form(
- FPDFDOC_InitFormFillEnvironment(doc.get(), &form_callbacks));
- if (!OnFormFillEnvLoaded(doc.get()))
- return;
-
- FPDF_SetFormFieldHighlightColor(form.get(), FPDF_FORMFIELD_UNKNOWN, 0xFFE4DD);
- FPDF_SetFormFieldHighlightAlpha(form.get(), 100);
- FORM_DoDocumentJSAction(form.get());
- FORM_DoDocumentOpenAction(form.get());
-
- int page_count = FPDF_GetPageCount(doc.get());
- for (int i = 0; i < page_count; ++i) {
- if (bIsLinearized) {
- nRet = PDF_DATA_NOTAVAIL;
- while (nRet == PDF_DATA_NOTAVAIL)
- nRet = FPDFAvail_IsPageAvail(pdf_avail.get(), i, &hints);
-
- if (nRet == PDF_DATA_ERROR)
- return;
- }
- RenderPage(doc.get(), form.get(), i);
- }
- FORM_DoDocumentAAction(form.get(), FPDFDOC_AACTION_WC);
-}
-
-bool PDFiumFuzzerHelper::RenderPage(FPDF_DOCUMENT doc,
- FPDF_FORMHANDLE form,
- const int page_index) {
- ScopedFPDFPage page(FPDF_LoadPage(doc, page_index));
- if (!page)
- return false;
-
- ScopedFPDFTextPage text_page(FPDFText_LoadPage(page.get()));
- FORM_OnAfterLoadPage(page.get(), form);
- FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_OPEN);
-
- const double scale = 1.0;
- int width = static_cast<int>(FPDF_GetPageWidth(page.get()) * scale);
- int height = static_cast<int>(FPDF_GetPageHeight(page.get()) * scale);
- ScopedFPDFBitmap bitmap(FPDFBitmap_Create(width, height, 0));
- if (bitmap) {
- FPDFBitmap_FillRect(bitmap.get(), 0, 0, width, height, 0xFFFFFFFF);
- FPDF_RenderPageBitmap(bitmap.get(), page.get(), 0, 0, width, height, 0, 0);
- FPDF_FFLDraw(form, bitmap.get(), page.get(), 0, 0, width, height, 0, 0);
- }
- FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_CLOSE);
- FORM_OnBeforeClosePage(page.get(), form);
- return !!bitmap;
-}
-
-// Initialize the library once for all runs of the fuzzer.
-struct TestCase {
- TestCase() {
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
- platform = InitializeV8ForPDFiumWithStartupData(
- ProgramPath(), "", &natives_blob, &snapshot_blob);
-#else
- platform = InitializeV8ForPDFium(ProgramPath());
-#endif
-
- memset(&config, '\0', sizeof(config));
- config.version = 2;
- config.m_pUserFontPaths = nullptr;
- config.m_pIsolate = nullptr;
- config.m_v8EmbedderSlot = 0;
- FPDF_InitLibraryWithConfig(&config);
-
- memset(&unsupport_info, '\0', sizeof(unsupport_info));
- unsupport_info.version = 1;
- unsupport_info.FSDK_UnSupport_Handler = ExampleUnsupportedHandler;
- FSDK_SetUnSpObjProcessHandler(&unsupport_info);
- }
-
- std::unique_ptr<v8::Platform> platform;
- v8::StartupData natives_blob;
- v8::StartupData snapshot_blob;
- FPDF_LIBRARY_CONFIG config;
- UNSUPPORT_INFO unsupport_info;
-};
-
-static TestCase* test_case = new TestCase();
diff --git a/chromium/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h b/chromium/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h
deleted file mode 100644
index 8a3fe8cac9d..00000000000
--- a/chromium/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef PDF_PDFIUM_FUZZERS_PDFIUM_FUZZER_HELPER_H_
-#define PDF_PDFIUM_FUZZERS_PDFIUM_FUZZER_HELPER_H_
-
-// This fuzzer is simplified & cleaned up pdfium/samples/pdfium_test.cc
-
-#include "third_party/pdfium/public/fpdf_ext.h"
-#include "third_party/pdfium/public/fpdf_formfill.h"
-#include "third_party/pdfium/public/fpdfview.h"
-#include "v8/include/v8.h"
-
-class PDFiumFuzzerHelper {
- public:
- virtual ~PDFiumFuzzerHelper();
-
- void RenderPdf(const char* pBuf, size_t len);
-
- virtual int GetFormCallbackVersion() const = 0;
- virtual bool OnFormFillEnvLoaded(FPDF_DOCUMENT doc);
-
- protected:
- PDFiumFuzzerHelper();
-
- private:
- bool RenderPage(FPDF_DOCUMENT doc,
- FPDF_FORMHANDLE form,
- const int page_index);
-};
-
-#endif // PDF_PDFIUM_FUZZERS_PDFIUM_FUZZER_HELPER_H_
diff --git a/chromium/pdf/pdfium/fuzzers/pdfium_xfa_fuzzer.cc b/chromium/pdf/pdfium/fuzzers/pdfium_xfa_fuzzer.cc
deleted file mode 100644
index bac055c83e0..00000000000
--- a/chromium/pdf/pdfium/fuzzers/pdfium_xfa_fuzzer.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 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.
-
-#include "pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h"
-
-class PDFiumXFAFuzzer : public PDFiumFuzzerHelper {
- public:
- PDFiumXFAFuzzer() : PDFiumFuzzerHelper() {}
- ~PDFiumXFAFuzzer() override {}
-
- int GetFormCallbackVersion() const override { return 2; }
-
- // Return false if XFA doesn't load as otherwise we're duplicating the work
- // done by the non-xfa fuzzer.
- bool OnFormFillEnvLoaded(FPDF_DOCUMENT doc) override {
- int form_type = FPDF_GetFormType(doc);
- if (form_type != FORMTYPE_XFA_FULL && form_type != FORMTYPE_XFA_FOREGROUND)
- return false;
- return FPDF_LoadXFA(doc);
- }
-};
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- PDFiumXFAFuzzer fuzzer;
- fuzzer.RenderPdf(reinterpret_cast<const char*>(data), size);
- return 0;
-}
diff --git a/chromium/pdf/pdfium/pdfium_engine.cc b/chromium/pdf/pdfium/pdfium_engine.cc
index 5e47623b9ee..80fd5a03f3d 100644
--- a/chromium/pdf/pdfium/pdfium_engine.cc
+++ b/chromium/pdf/pdfium/pdfium_engine.cc
@@ -76,20 +76,20 @@ static_assert(static_cast<int>(PDFEngine::FormType::kCount) == FORMTYPE_COUNT,
namespace {
-const int32_t kPageShadowTop = 3;
-const int32_t kPageShadowBottom = 7;
-const int32_t kPageShadowLeft = 5;
-const int32_t kPageShadowRight = 5;
+constexpr int32_t kPageShadowTop = 3;
+constexpr int32_t kPageShadowBottom = 7;
+constexpr int32_t kPageShadowLeft = 5;
+constexpr int32_t kPageShadowRight = 5;
-const int32_t kPageSeparatorThickness = 4;
-const int32_t kHighlightColorR = 153;
-const int32_t kHighlightColorG = 193;
-const int32_t kHighlightColorB = 218;
+constexpr int32_t kPageSeparatorThickness = 4;
+constexpr int32_t kHighlightColorR = 153;
+constexpr int32_t kHighlightColorG = 193;
+constexpr int32_t kHighlightColorB = 218;
-const uint32_t kPendingPageColor = 0xFFEEEEEE;
+constexpr uint32_t kPendingPageColor = 0xFFEEEEEE;
-const uint32_t kFormHighlightColor = 0xFFE4DD;
-const int32_t kFormHighlightAlpha = 100;
+constexpr uint32_t kFormHighlightColor = 0xFFE4DD;
+constexpr int32_t kFormHighlightAlpha = 100;
constexpr int kMaxPasswordTries = 3;
@@ -105,12 +105,12 @@ constexpr bool kViewerImplementedPanning = true;
// See Table 3.20 in
// http://www.adobe.com/devnet/acrobat/pdfs/pdf_reference_1-7.pdf
-const uint32_t kPDFPermissionPrintLowQualityMask = 1 << 2;
-const uint32_t kPDFPermissionPrintHighQualityMask = 1 << 11;
-const uint32_t kPDFPermissionCopyMask = 1 << 4;
-const uint32_t kPDFPermissionCopyAccessibleMask = 1 << 9;
+constexpr uint32_t kPDFPermissionPrintLowQualityMask = 1 << 2;
+constexpr uint32_t kPDFPermissionPrintHighQualityMask = 1 << 11;
+constexpr uint32_t kPDFPermissionCopyMask = 1 << 4;
+constexpr uint32_t kPDFPermissionCopyAccessibleMask = 1 << 9;
-const int32_t kLoadingTextVerticalOffset = 50;
+constexpr int32_t kLoadingTextVerticalOffset = 50;
// The maximum amount of time we'll spend doing a paint before we give back
// control of the thread.
@@ -131,10 +131,6 @@ constexpr base::TimeDelta kMaxProgressivePaintTime =
constexpr base::TimeDelta kMaxInitialProgressivePaintTime =
base::TimeDelta::FromMilliseconds(250);
-// Flag to turn edit mode tracking on.
-// Do not flip until form saving is completely functional.
-constexpr bool kIsEditModeTracked = false;
-
PDFiumEngine* g_engine_for_fontmapper = nullptr;
#if defined(OS_LINUX)
@@ -147,8 +143,8 @@ PP_BrowserFont_Trusted_Weight WeightToBrowserFontTrustedWeight(int weight) {
"PP_BrowserFont_Trusted_Weight min");
static_assert(PP_BROWSERFONT_TRUSTED_WEIGHT_900 == 8,
"PP_BrowserFont_Trusted_Weight max");
- const int kMinimumWeight = 100;
- const int kMaximumWeight = 900;
+ constexpr int kMinimumWeight = 100;
+ constexpr int kMaximumWeight = 900;
int normalized_weight =
std::min(std::max(weight, kMinimumWeight), kMaximumWeight);
normalized_weight = (normalized_weight / 100) - 1;
@@ -240,7 +236,7 @@ void* MapFont(FPDF_SYSFONTINFO*,
// Map from the standard PDF fonts to TrueType font names.
size_t i;
- for (i = 0; i < arraysize(kPdfFontSubstitutions); ++i) {
+ for (i = 0; i < base::size(kPdfFontSubstitutions); ++i) {
if (strcmp(face, kPdfFontSubstitutions[i].pdf_name) == 0) {
description.set_face(kPdfFontSubstitutions[i].face);
if (kPdfFontSubstitutions[i].bold)
@@ -251,7 +247,7 @@ void* MapFont(FPDF_SYSFONTINFO*,
}
}
- if (i == arraysize(kPdfFontSubstitutions)) {
+ if (i == base::size(kPdfFontSubstitutions)) {
// Convert to UTF-8 before calling set_face().
std::string face_utf8;
if (base::IsStringUTF8(face)) {
@@ -447,7 +443,7 @@ void FormatStringWithHyphens(base::string16* text) {
std::vector<HyphenPosition> hyphen_positions;
HyphenPosition current_hyphen_position;
bool current_hyphen_position_is_valid = false;
- const base::char16 kPdfiumHyphenEOL = 0xfffe;
+ constexpr base::char16 kPdfiumHyphenEOL = 0xfffe;
for (size_t i = 0; i < text->size(); ++i) {
const base::char16& current_char = (*text)[i];
@@ -471,7 +467,7 @@ void FormatStringWithHyphens(base::string16* text) {
// With all the hyphen positions, do the search and replace.
while (!hyphen_positions.empty()) {
- static const base::char16 kCr[] = {L'\r', L'\0'};
+ static constexpr base::char16 kCr[] = {L'\r', L'\0'};
const HyphenPosition& position = hyphen_positions.back();
if (position.next_whitespace_position != 0) {
(*text)[position.next_whitespace_position] = L'\n';
@@ -482,16 +478,16 @@ void FormatStringWithHyphens(base::string16* text) {
}
// Adobe Reader also get rid of trailing spaces right before a CRLF.
- static const base::char16 kSpaceCrCn[] = {L' ', L'\r', L'\n', L'\0'};
- static const base::char16 kCrCn[] = {L'\r', L'\n', L'\0'};
+ static constexpr base::char16 kSpaceCrCn[] = {L' ', L'\r', L'\n', L'\0'};
+ static constexpr base::char16 kCrCn[] = {L'\r', L'\n', L'\0'};
base::ReplaceSubstringsAfterOffset(text, 0, kSpaceCrCn, kCrCn);
}
// Replace CR/LF with just LF on POSIX.
void FormatStringForOS(base::string16* text) {
#if defined(OS_POSIX)
- static const base::char16 kCr[] = {L'\r', L'\0'};
- static const base::char16 kBlank[] = {L'\0'};
+ static constexpr base::char16 kCr[] = {L'\r', L'\0'};
+ static constexpr base::char16 kBlank[] = {L'\0'};
base::ReplaceChars(*text, kCr, kBlank, text);
#elif defined(OS_WIN)
// Do nothing
@@ -515,7 +511,6 @@ bool FindMultipleClickBoundary(bool is_double_click, base::char16 cur) {
if (cur < 128)
return true;
- static constexpr base::char16 kZeroWidthSpace = 0x200B;
if (cur == kZeroWidthSpace)
return true;
@@ -891,6 +886,13 @@ std::string PDFiumEngine::GetMetadata(const std::string& key) {
return GetDocumentMetadata(doc(), key);
}
+std::vector<uint8_t> PDFiumEngine::GetSaveData() {
+ PDFiumMemBufferFileWrite output_file_write;
+ if (!FPDF_SaveAsCopy(doc(), &output_file_write, 0))
+ return std::vector<uint8_t>();
+ return output_file_write.TakeBuffer();
+}
+
void PDFiumEngine::OnPendingRequestComplete() {
if (!process_when_pending_request_complete_)
return;
@@ -1125,17 +1127,17 @@ pp::Resource PDFiumEngine::PrintPages(
if ((print_settings.format & PP_PRINTOUTPUTFORMAT_PDF) &&
HasPermission(PERMISSION_PRINT_HIGH_QUALITY)) {
- return PrintPagesAsPDF(page_ranges, page_range_count, print_settings,
+ return PrintPagesAsPdf(page_ranges, page_range_count, print_settings,
pdf_print_settings);
}
if (HasPermission(PERMISSION_PRINT_LOW_QUALITY)) {
- return PrintPagesAsRasterPDF(page_ranges, page_range_count, print_settings,
+ return PrintPagesAsRasterPdf(page_ranges, page_range_count, print_settings,
pdf_print_settings);
}
return pp::Resource();
}
-pp::Buffer_Dev PDFiumEngine::PrintPagesAsRasterPDF(
+pp::Buffer_Dev PDFiumEngine::PrintPagesAsRasterPdf(
const PP_PrintPageNumberRange_Dev* page_ranges,
uint32_t page_range_count,
const PP_PrintSettings_Dev& print_settings,
@@ -1152,11 +1154,12 @@ pp::Buffer_Dev PDFiumEngine::PrintPagesAsRasterPDF(
g_last_instance_id = client_->GetPluginInstance()->pp_instance();
#endif
- return print_.PrintPagesAsRasterPDF(page_ranges, page_range_count,
- print_settings, pdf_print_settings);
+ return ConvertPdfToBufferDev(
+ print_.PrintPagesAsPdf(page_ranges, page_range_count, print_settings,
+ pdf_print_settings, /*raster=*/true));
}
-pp::Buffer_Dev PDFiumEngine::PrintPagesAsPDF(
+pp::Buffer_Dev PDFiumEngine::PrintPagesAsPdf(
const PP_PrintPageNumberRange_Dev* page_ranges,
uint32_t page_range_count,
const PP_PrintSettings_Dev& print_settings,
@@ -1175,8 +1178,20 @@ pp::Buffer_Dev PDFiumEngine::PrintPagesAsPDF(
pages_[page_number]->Unload();
}
- return print_.PrintPagesAsPDF(page_ranges, page_range_count, print_settings,
- pdf_print_settings);
+ return ConvertPdfToBufferDev(
+ print_.PrintPagesAsPdf(page_ranges, page_range_count, print_settings,
+ pdf_print_settings, /*raster=*/false));
+}
+
+pp::Buffer_Dev PDFiumEngine::ConvertPdfToBufferDev(
+ const std::vector<uint8_t>& pdf_data) {
+ pp::Buffer_Dev buffer;
+ if (!pdf_data.empty()) {
+ buffer = pp::Buffer_Dev(GetPluginInstance(), pdf_data.size());
+ if (!buffer.is_null())
+ memcpy(buffer.data(), pdf_data.data(), pdf_data.size());
+ }
+ return buffer;
}
void PDFiumEngine::KillFormFocus() {
@@ -1919,28 +1934,88 @@ void PDFiumEngine::SearchUsingICU(const base::string16& term,
character_to_start_searching_from, text_length, data);
api_string_adapter.Close(written);
+ base::string16 adjusted_page_text;
+ adjusted_page_text.reserve(page_text.size());
+ // Values in |removed_indices| are in the adjusted text index space and
+ // indicate a character was removed from the page text before the given
+ // index. If multiple characters are removed in a row then there will be
+ // multiple entries with the same value.
+ std::vector<size_t> removed_indices;
+ // When walking through the page text collapse any whitespace regions,
+ // including \r and \n, down to a single ' ' character. This code does
+ // not use base::CollapseWhitespace(), because that function does not
+ // return where the collapsing occurs, but uses the same underlying list of
+ // whitespace characters. Calculating where the collapsed regions are after
+ // the fact is as complex as collapsing them manually.
+ for (size_t i = 0; i < page_text.size(); i++) {
+ base::char16 c = page_text[i];
+ // Collapse whitespace regions by inserting a ' ' into the
+ // adjusted text and recording any removed whitespace indices as preceding
+ // it.
+ if (base::IsUnicodeWhitespace(c)) {
+ size_t whitespace_region_begin = i;
+ while (i < page_text.size() && base::IsUnicodeWhitespace(page_text[i]))
+ ++i;
+
+ size_t count = i - whitespace_region_begin - 1;
+ removed_indices.insert(removed_indices.end(), count,
+ adjusted_page_text.size());
+ adjusted_page_text.push_back(' ');
+ if (i >= page_text.size())
+ break;
+ c = page_text[i];
+ }
+
+ if (IsIgnorableCharacter(c))
+ removed_indices.push_back(adjusted_page_text.size());
+ else
+ adjusted_page_text.push_back(c);
+ }
+
std::vector<PDFEngine::Client::SearchStringResult> results =
- client_->SearchString(page_text.c_str(), term.c_str(), case_sensitive);
+ client_->SearchString(adjusted_page_text.c_str(), term.c_str(),
+ case_sensitive);
for (const auto& result : results) {
+ // Need to convert from adjusted page text start to page text start, by
+ // incrementing for all the characters adjusted before it in the string.
+ auto removed_indices_begin = std::upper_bound(
+ removed_indices.begin(), removed_indices.end(), result.start_index);
+ size_t page_text_result_start_index =
+ result.start_index +
+ std::distance(removed_indices.begin(), removed_indices_begin);
+
+ // Need to convert the adjusted page length into a page text length, since
+ // the matching range may have adjusted characters within it. This
+ // conversion only cares about skipped characters in the result interval.
+ auto removed_indices_end =
+ std::upper_bound(removed_indices_begin, removed_indices.end(),
+ result.start_index + result.length);
+ int term_removed_count =
+ std::distance(removed_indices_begin, removed_indices_end);
+ int page_text_result_length = result.length + term_removed_count;
+
// Need to map the indexes from the page text, which may have generated
// characters like space etc, to character indices from the page.
int text_to_start_searching_from = FPDFText_GetTextIndexFromCharIndex(
pages_[current_page]->GetTextPage(), character_to_start_searching_from);
- int temp_start = result.start_index + text_to_start_searching_from;
+ int temp_start =
+ page_text_result_start_index + text_to_start_searching_from;
int start = FPDFText_GetCharIndexFromTextIndex(
pages_[current_page]->GetTextPage(), temp_start);
int end = FPDFText_GetCharIndexFromTextIndex(
- pages_[current_page]->GetTextPage(), temp_start + result.length);
+ pages_[current_page]->GetTextPage(),
+ temp_start + page_text_result_length);
// If |term| occurs at the end of a page, then |end| will be -1 due to the
// index being out of bounds. Compensate for this case so the range
// character count calculation below works out.
- if (temp_start + result.length == original_text_length) {
+ if (temp_start + page_text_result_length == original_text_length) {
DCHECK_EQ(-1, end);
end = original_text_length;
}
DCHECK_LT(start, end);
- DCHECK_EQ(term.size(), static_cast<size_t>(end - start));
+ DCHECK_EQ(term.size() + term_removed_count,
+ static_cast<size_t>(end - start));
AddFindResult(PDFiumRange(pages_[current_page].get(), start, end - start));
}
}
@@ -2275,7 +2350,7 @@ pp::VarDictionary PDFiumEngine::TraverseBookmarks(FPDF_BOOKMARK bookmark,
pp::VarArray children;
// Don't trust PDFium to handle circular bookmarks.
- const unsigned int kMaxDepth = 128;
+ constexpr unsigned int kMaxDepth = 128;
if (depth < kMaxDepth) {
int child_index = 0;
std::set<FPDF_BOOKMARK> seen_bookmarks;
@@ -3363,7 +3438,7 @@ void PDFiumEngine::DrawPageShadow(const pp::Rect& page_rc,
clip_rect.Offset(page_offset_);
// Page drop shadow parameters.
- const double factor = 0.5;
+ constexpr double factor = 0.5;
uint32_t depth =
std::max(std::max(page_rect.x() - shadow_rect.x(),
page_rect.y() - shadow_rect.y()),
@@ -3469,7 +3544,7 @@ void PDFiumEngine::SetSelecting(bool selecting) {
}
void PDFiumEngine::SetEditMode(bool edit_mode) {
- if (!kIsEditModeTracked || edit_mode_ == edit_mode)
+ if (edit_mode_ == edit_mode)
return;
edit_mode_ = edit_mode;
diff --git a/chromium/pdf/pdfium/pdfium_engine.h b/chromium/pdf/pdfium/pdfium_engine.h
index 5bc0029ca13..4d931205046 100644
--- a/chromium/pdf/pdfium/pdfium_engine.h
+++ b/chromium/pdf/pdfium/pdfium_engine.h
@@ -119,6 +119,7 @@ class PDFiumEngine : public PDFEngine,
void AppendBlankPages(int num_pages) override;
void AppendPage(PDFEngine* engine, int index) override;
std::string GetMetadata(const std::string& key) override;
+ std::vector<uint8_t> GetSaveData() override;
void SetCaretPosition(const pp::Point& position) override;
void MoveRangeSelectionExtent(const pp::Point& extent) override;
void SetSelectionBounds(const pp::Point& base,
@@ -300,18 +301,20 @@ class PDFiumEngine : public PDFEngine,
bool ExtendSelection(int page_index, int char_index);
- pp::Buffer_Dev PrintPagesAsRasterPDF(
+ pp::Buffer_Dev PrintPagesAsRasterPdf(
const PP_PrintPageNumberRange_Dev* page_ranges,
uint32_t page_range_count,
const PP_PrintSettings_Dev& print_settings,
const PP_PdfPrintSettings_Dev& pdf_print_settings);
- pp::Buffer_Dev PrintPagesAsPDF(
+ pp::Buffer_Dev PrintPagesAsPdf(
const PP_PrintPageNumberRange_Dev* page_ranges,
uint32_t page_range_count,
const PP_PrintSettings_Dev& print_settings,
const PP_PdfPrintSettings_Dev& pdf_print_settings);
+ pp::Buffer_Dev ConvertPdfToBufferDev(const std::vector<uint8_t>& pdf_data);
+
// Checks if |page| has selected text in a form element. If so, sets that as
// the plugin's text selection.
void SetFormSelectedText(FPDF_FORMHANDLE form_handle, FPDF_PAGE page);
diff --git a/chromium/pdf/pdfium/pdfium_engine_exports.cc b/chromium/pdf/pdfium/pdfium_engine_exports.cc
index 8b5f69b6c27..e0465a84911 100644
--- a/chromium/pdf/pdfium/pdfium_engine_exports.cc
+++ b/chromium/pdf/pdfium/pdfium_engine_exports.cc
@@ -16,6 +16,7 @@
#include "third_party/pdfium/public/cpp/fpdf_scopers.h"
#include "third_party/pdfium/public/fpdf_ppo.h"
#include "third_party/pdfium/public/fpdfview.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
using printing::ConvertUnitDouble;
@@ -119,31 +120,12 @@ ScopedFPDFDocument CreatePdfDoc(
return doc;
}
-std::vector<uint8_t> CreateNupPdfDocument(FPDF_DOCUMENT doc,
- size_t pages_per_sheet,
- const gfx::Size& page_size) {
- int page_size_width = page_size.width();
- int page_size_height = page_size.height();
-
- printing::NupParameters nup_params;
- bool is_landscape = PDFiumPrint::IsSourcePdfLandscape(doc);
- nup_params.SetParameters(pages_per_sheet, is_landscape);
- bool paper_is_landscape = page_size_width > page_size_height;
- if (nup_params.landscape() != paper_is_landscape)
- std::swap(page_size_width, page_size_height);
-
- ScopedFPDFDocument output_doc_nup(FPDF_ImportNPagesToOne(
- doc, page_size_width, page_size_height, nup_params.num_pages_on_x_axis(),
- nup_params.num_pages_on_y_axis()));
-
- if (!output_doc_nup)
- return std::vector<uint8_t>();
-
- PDFiumMemBufferFileWrite output_file_write;
- if (!FPDF_SaveAsCopy(output_doc_nup.get(), &output_file_write, 0))
- return std::vector<uint8_t>();
-
- return output_file_write.TakeBuffer();
+bool IsValidPrintableArea(const gfx::Size& page_size,
+ const gfx::Rect& printable_area) {
+ return !printable_area.IsEmpty() && printable_area.x() >= 0 &&
+ printable_area.y() >= 0 &&
+ printable_area.right() <= page_size.width() &&
+ printable_area.bottom() <= page_size.height();
}
} // namespace
@@ -302,23 +284,33 @@ bool PDFiumEngineExports::RenderPDFPageToBitmap(
std::vector<uint8_t> PDFiumEngineExports::ConvertPdfPagesToNupPdf(
std::vector<base::span<const uint8_t>> input_buffers,
size_t pages_per_sheet,
- const gfx::Size& page_size) {
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) {
+ if (!IsValidPrintableArea(page_size, printable_area))
+ return std::vector<uint8_t>();
+
ScopedFPDFDocument doc = CreatePdfDoc(std::move(input_buffers));
if (!doc)
return std::vector<uint8_t>();
- return CreateNupPdfDocument(doc.get(), pages_per_sheet, page_size);
+ return PDFiumPrint::CreateNupPdf(std::move(doc), pages_per_sheet, page_size,
+ printable_area);
}
std::vector<uint8_t> PDFiumEngineExports::ConvertPdfDocumentToNupPdf(
base::span<const uint8_t> input_buffer,
size_t pages_per_sheet,
- const gfx::Size& page_size) {
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) {
+ if (!IsValidPrintableArea(page_size, printable_area))
+ return std::vector<uint8_t>();
+
ScopedFPDFDocument doc = LoadPdfData(input_buffer);
if (!doc)
return std::vector<uint8_t>();
- return CreateNupPdfDocument(doc.get(), pages_per_sheet, page_size);
+ return PDFiumPrint::CreateNupPdf(std::move(doc), pages_per_sheet, page_size,
+ printable_area);
}
bool PDFiumEngineExports::GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
diff --git a/chromium/pdf/pdfium/pdfium_engine_exports.h b/chromium/pdf/pdfium/pdfium_engine_exports.h
index 04de13d66c0..02832594bc0 100644
--- a/chromium/pdf/pdfium/pdfium_engine_exports.h
+++ b/chromium/pdf/pdfium/pdfium_engine_exports.h
@@ -8,7 +8,6 @@
#include <stddef.h>
#include <stdint.h>
-#include "base/containers/span.h"
#include "build/build_config.h"
#include "pdf/pdf_engine.h"
@@ -38,11 +37,13 @@ class PDFiumEngineExports : public PDFEngineExports {
std::vector<uint8_t> ConvertPdfPagesToNupPdf(
std::vector<base::span<const uint8_t>> input_buffers,
size_t pages_per_sheet,
- const gfx::Size& page_size) override;
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) override;
std::vector<uint8_t> ConvertPdfDocumentToNupPdf(
base::span<const uint8_t> input_buffer,
size_t pages_per_sheet,
- const gfx::Size& page_size) override;
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) override;
bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
int* page_count,
double* max_page_width) override;
diff --git a/chromium/pdf/pdfium/pdfium_engine_exports_unittest.cc b/chromium/pdf/pdfium/pdfium_engine_exports_unittest.cc
index ab01ba13e8b..ed3e31c39ab 100644
--- a/chromium/pdf/pdfium/pdfium_engine_exports_unittest.cc
+++ b/chromium/pdf/pdfium/pdfium_engine_exports_unittest.cc
@@ -10,6 +10,7 @@
#include "pdf/pdf.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace chrome_pdf {
@@ -102,14 +103,26 @@ TEST_F(PDFiumEngineExportsTest, ConvertPdfPagesToNupPdf) {
ASSERT_TRUE(base::ReadFileToString(pdf_path, &pdf_data));
std::vector<base::span<const uint8_t>> pdf_buffers;
- std::vector<uint8_t> output_pdf_buffer =
- ConvertPdfPagesToNupPdf(pdf_buffers, 1, gfx::Size(512, 792));
+ std::vector<uint8_t> output_pdf_buffer = ConvertPdfPagesToNupPdf(
+ pdf_buffers, 1, gfx::Size(612, 792), gfx::Rect(22, 20, 570, 750));
EXPECT_TRUE(output_pdf_buffer.empty());
pdf_buffers.push_back(base::as_bytes(base::make_span(pdf_data)));
pdf_buffers.push_back(base::as_bytes(base::make_span(pdf_data)));
- output_pdf_buffer =
- ConvertPdfPagesToNupPdf(pdf_buffers, 2, gfx::Size(512, 792));
+ output_pdf_buffer = ConvertPdfPagesToNupPdf(
+ pdf_buffers, 2, gfx::Size(612, 792), gfx::Rect(22, 20, 0, 750));
+ EXPECT_TRUE(output_pdf_buffer.empty());
+ output_pdf_buffer = ConvertPdfPagesToNupPdf(
+ pdf_buffers, 2, gfx::Size(612, 792), gfx::Rect(22, 20, 570, 0));
+ EXPECT_TRUE(output_pdf_buffer.empty());
+ output_pdf_buffer = ConvertPdfPagesToNupPdf(
+ pdf_buffers, 2, gfx::Size(612, 792), gfx::Rect(300, 20, 570, 750));
+ EXPECT_TRUE(output_pdf_buffer.empty());
+ output_pdf_buffer = ConvertPdfPagesToNupPdf(
+ pdf_buffers, 2, gfx::Size(612, 792), gfx::Rect(22, 400, 570, 750));
+ EXPECT_TRUE(output_pdf_buffer.empty());
+ output_pdf_buffer = ConvertPdfPagesToNupPdf(
+ pdf_buffers, 2, gfx::Size(612, 792), gfx::Rect(22, 20, 570, 750));
ASSERT_GT(output_pdf_buffer.size(), 0U);
base::span<const uint8_t> output_pdf_span =
@@ -122,7 +135,7 @@ TEST_F(PDFiumEngineExportsTest, ConvertPdfPagesToNupPdf) {
double height;
ASSERT_TRUE(GetPDFPageSizeByIndex(output_pdf_span, 0, &width, &height));
EXPECT_DOUBLE_EQ(792.0, width);
- EXPECT_DOUBLE_EQ(512.0, height);
+ EXPECT_DOUBLE_EQ(612.0, height);
}
TEST_F(PDFiumEngineExportsTest, ConvertPdfDocumentToNupPdf) {
@@ -132,13 +145,13 @@ TEST_F(PDFiumEngineExportsTest, ConvertPdfDocumentToNupPdf) {
ASSERT_TRUE(base::ReadFileToString(pdf_path, &pdf_data));
base::span<const uint8_t> pdf_buffer;
- std::vector<uint8_t> output_pdf_buffer =
- ConvertPdfDocumentToNupPdf(pdf_buffer, 1, gfx::Size(512, 792));
+ std::vector<uint8_t> output_pdf_buffer = ConvertPdfDocumentToNupPdf(
+ pdf_buffer, 1, gfx::Size(612, 792), gfx::Rect(32, 20, 570, 750));
EXPECT_TRUE(output_pdf_buffer.empty());
pdf_buffer = base::as_bytes(base::make_span(pdf_data));
- output_pdf_buffer =
- ConvertPdfDocumentToNupPdf(pdf_buffer, 4, gfx::Size(512, 792));
+ output_pdf_buffer = ConvertPdfDocumentToNupPdf(
+ pdf_buffer, 4, gfx::Size(612, 792), gfx::Rect(22, 20, 570, 750));
ASSERT_GT(output_pdf_buffer.size(), 0U);
base::span<const uint8_t> output_pdf_span =
@@ -151,7 +164,7 @@ TEST_F(PDFiumEngineExportsTest, ConvertPdfDocumentToNupPdf) {
double height;
ASSERT_TRUE(
GetPDFPageSizeByIndex(output_pdf_span, page_number, &width, &height));
- EXPECT_DOUBLE_EQ(512.0, width);
+ EXPECT_DOUBLE_EQ(612.0, width);
EXPECT_DOUBLE_EQ(792.0, height);
}
}
diff --git a/chromium/pdf/pdfium/pdfium_mem_buffer_file_write.h b/chromium/pdf/pdfium/pdfium_mem_buffer_file_write.h
index 03c54bb6380..82e82d23684 100644
--- a/chromium/pdf/pdfium/pdfium_mem_buffer_file_write.h
+++ b/chromium/pdf/pdfium/pdfium_mem_buffer_file_write.h
@@ -6,6 +6,7 @@
#define PDF_PDFIUM_PDFIUM_MEM_BUFFER_FILE_WRITE_H_
#include <stddef.h>
+#include <stdint.h>
#include <vector>
diff --git a/chromium/pdf/pdfium/pdfium_page.cc b/chromium/pdf/pdfium/pdfium_page.cc
index 37b4db3dfe7..941b8594268 100644
--- a/chromium/pdf/pdfium/pdfium_page.cc
+++ b/chromium/pdf/pdfium/pdfium_page.cc
@@ -134,26 +134,6 @@ FPDF_PAGE PDFiumPage::GetPage() {
return page();
}
-FPDF_PAGE PDFiumPage::GetPrintPage() {
- ScopedUnsupportedFeature scoped_unsupported_feature(engine_);
- ScopedSubstFont scoped_subst_font(engine_);
- if (!available_)
- return nullptr;
- if (!page_) {
- ScopedUnloadPreventer scoped_unload_preventer(this);
- page_.reset(FPDF_LoadPage(engine_->doc(), index_));
- }
- return page();
-}
-
-void PDFiumPage::ClosePrintPage() {
- // Do not close |page_| while in the middle of a load.
- if (preventing_unload_count_)
- return;
-
- page_.reset();
-}
-
FPDF_TEXTPAGE PDFiumPage::GetTextPage() {
if (!available_)
return nullptr;
diff --git a/chromium/pdf/pdfium/pdfium_page.h b/chromium/pdf/pdfium/pdfium_page.h
index 86daadc0ed5..ae9b186c101 100644
--- a/chromium/pdf/pdfium/pdfium_page.h
+++ b/chromium/pdf/pdfium/pdfium_page.h
@@ -33,10 +33,6 @@ class PDFiumPage {
void Unload();
// Gets the FPDF_PAGE for this page, loading and parsing it if necessary.
FPDF_PAGE GetPage();
- // Get the FPDF_PAGE for printing.
- FPDF_PAGE GetPrintPage();
- // Close the printing page.
- void ClosePrintPage();
// Returns FPDF_TEXTPAGE for the page, loading and parsing it if necessary.
FPDF_TEXTPAGE GetTextPage();
diff --git a/chromium/pdf/pdfium/pdfium_print.cc b/chromium/pdf/pdfium/pdfium_print.cc
index 037cfd4660c..73e034ca9d6 100644
--- a/chromium/pdf/pdfium/pdfium_print.cc
+++ b/chromium/pdf/pdfium/pdfium_print.cc
@@ -4,6 +4,7 @@
#include "pdf/pdfium/pdfium_print.h"
+#include <algorithm>
#include <string>
#include <utility>
@@ -15,13 +16,14 @@
#include "ppapi/c/dev/ppp_printing_dev.h"
#include "ppapi/c/private/ppp_pdf.h"
#include "printing/nup_parameters.h"
+#include "printing/page_setup.h"
#include "printing/units.h"
-#include "third_party/pdfium/public/cpp/fpdf_scopers.h"
#include "third_party/pdfium/public/fpdf_flatten.h"
#include "third_party/pdfium/public/fpdf_ppo.h"
#include "third_party/pdfium/public/fpdf_transformpage.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
using printing::ConvertUnit;
using printing::ConvertUnitDouble;
@@ -37,6 +39,11 @@ bool ShouldDoNup(int pages_per_sheet) {
return pages_per_sheet > 1;
}
+// Returns the valid, positive page count, or 0 on failure.
+int GetDocumentPageCount(FPDF_DOCUMENT doc) {
+ return std::max(FPDF_GetPageCount(doc), 0);
+}
+
// Set the destination page size and content area in points based on source
// page rotation and orientation.
//
@@ -165,6 +172,45 @@ void FitContentsToPrintableAreaIfRequired(
}
}
+// Takes the same parameters as PDFiumPrint::CreateNupPdf().
+// On success, returns the N-up version of |doc|. On failure, returns nullptr.
+ScopedFPDFDocument CreateNupPdfDocument(ScopedFPDFDocument doc,
+ size_t pages_per_sheet,
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) {
+ DCHECK(doc);
+ DCHECK(ShouldDoNup(pages_per_sheet));
+
+ int page_size_width = page_size.width();
+ int page_size_height = page_size.height();
+
+ printing::NupParameters nup_params;
+ bool is_landscape = PDFiumPrint::IsSourcePdfLandscape(doc.get());
+ nup_params.SetParameters(pages_per_sheet, is_landscape);
+ bool paper_is_landscape = page_size_width > page_size_height;
+ if (nup_params.landscape() != paper_is_landscape)
+ std::swap(page_size_width, page_size_height);
+
+ ScopedFPDFDocument nup_doc(FPDF_ImportNPagesToOne(
+ doc.get(), page_size_width, page_size_height,
+ nup_params.num_pages_on_x_axis(), nup_params.num_pages_on_y_axis()));
+ if (nup_doc) {
+ PDFiumPrint::FitContentsToPrintableArea(nup_doc.get(), page_size,
+ printable_area);
+ }
+ return nup_doc;
+}
+
+std::vector<uint8_t> ConvertDocToBuffer(ScopedFPDFDocument doc) {
+ DCHECK(doc);
+
+ std::vector<uint8_t> buffer;
+ PDFiumMemBufferFileWrite output_file_write;
+ if (FPDF_SaveAsCopy(doc.get(), &output_file_write, 0))
+ buffer = output_file_write.TakeBuffer();
+ return buffer;
+}
+
int GetBlockForJpeg(void* param,
unsigned long pos,
unsigned char* buf,
@@ -217,6 +263,20 @@ std::vector<uint32_t> PDFiumPrint::GetPageNumbersFromPrintPageNumberRange(
return page_numbers;
}
+// static
+std::vector<uint8_t> PDFiumPrint::CreateNupPdf(
+ ScopedFPDFDocument doc,
+ size_t pages_per_sheet,
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) {
+ ScopedFPDFDocument nup_doc = CreateNupPdfDocument(
+ std::move(doc), pages_per_sheet, page_size, printable_area);
+ if (!nup_doc)
+ return std::vector<uint8_t>();
+ return ConvertDocToBuffer(std::move(nup_doc));
+}
+
+// static
bool PDFiumPrint::IsSourcePdfLandscape(FPDF_DOCUMENT doc) {
DCHECK(doc);
@@ -228,80 +288,37 @@ bool PDFiumPrint::IsSourcePdfLandscape(FPDF_DOCUMENT doc) {
return is_source_landscape;
}
-pp::Buffer_Dev PDFiumPrint::PrintPagesAsRasterPDF(
+// static
+void PDFiumPrint::FitContentsToPrintableArea(FPDF_DOCUMENT doc,
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area) {
+ PP_PrintSettings_Dev print_settings;
+ print_settings.paper_size = pp::Size(page_size.width(), page_size.height());
+ print_settings.printable_area =
+ pp::Rect(printable_area.x(), printable_area.y(), printable_area.width(),
+ printable_area.height());
+ print_settings.print_scaling_option =
+ PP_PRINTSCALINGOPTION_FIT_TO_PRINTABLE_AREA;
+ FitContentsToPrintableAreaIfRequired(doc, 1.0, print_settings);
+}
+
+std::vector<uint8_t> PDFiumPrint::PrintPagesAsPdf(
const PP_PrintPageNumberRange_Dev* page_ranges,
uint32_t page_range_count,
const PP_PrintSettings_Dev& print_settings,
- const PP_PdfPrintSettings_Dev& pdf_print_settings) {
- std::vector<PDFiumPage> pages_to_print;
- // width and height of source PDF pages.
- std::vector<std::pair<double, double>> source_page_sizes;
- // Collect pages to print and sizes of source pages.
- std::vector<uint32_t> page_numbers =
- PDFiumPrint::GetPageNumbersFromPrintPageNumberRange(page_ranges,
- page_range_count);
- for (uint32_t page_number : page_numbers) {
- ScopedFPDFPage pdf_page(FPDF_LoadPage(engine_->doc(), page_number));
- double source_page_width = FPDF_GetPageWidth(pdf_page.get());
- double source_page_height = FPDF_GetPageHeight(pdf_page.get());
- source_page_sizes.push_back(
- std::make_pair(source_page_width, source_page_height));
- // For computing size in pixels, use a square dpi since the source PDF page
- // has square DPI.
- int width_in_pixels =
- ConvertUnit(source_page_width, kPointsPerInch, print_settings.dpi);
- int height_in_pixels =
- ConvertUnit(source_page_height, kPointsPerInch, print_settings.dpi);
-
- pp::Rect rect(width_in_pixels, height_in_pixels);
- pages_to_print.push_back(PDFiumPage(engine_, page_number, rect, true));
- }
-
- ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
- DCHECK(output_doc);
-
- size_t i = 0;
- for (; i < pages_to_print.size(); ++i) {
- double source_page_width = source_page_sizes[i].first;
- double source_page_height = source_page_sizes[i].second;
-
- // Use |temp_doc| to compress image by saving PDF to |buffer|.
- pp::Buffer_Dev buffer;
- {
- ScopedFPDFDocument temp_doc(
- CreateSinglePageRasterPdf(source_page_width, source_page_height,
- print_settings, &pages_to_print[i]));
-
- if (!temp_doc)
- break;
-
- buffer = GetFlattenedPrintData(temp_doc.get());
- }
-
- PDFiumMemBufferFileRead file_read(buffer.data(), buffer.size());
- ScopedFPDFDocument temp_doc(FPDF_LoadCustomDocument(&file_read, nullptr));
- if (!FPDF_ImportPages(output_doc.get(), temp_doc.get(), "1", i))
- break;
- }
-
- pp::Buffer_Dev buffer;
- if (i == pages_to_print.size()) {
- FPDF_CopyViewerPreferences(output_doc.get(), engine_->doc());
- uint32_t pages_per_sheet = pdf_print_settings.pages_per_sheet;
- uint32_t scale_factor = pdf_print_settings.scale_factor;
- if (ShouldDoNup(pages_per_sheet)) {
- buffer = NupPdfToPdf(output_doc.get(), pages_per_sheet, print_settings);
- } else {
- FitContentsToPrintableAreaIfRequired(
- output_doc.get(), scale_factor / 100.0f, print_settings);
- buffer = GetPrintData(output_doc.get());
- }
- }
-
+ const PP_PdfPrintSettings_Dev& pdf_print_settings,
+ bool raster) {
+ std::vector<uint8_t> buffer;
+ ScopedFPDFDocument output_doc = CreatePrintPdf(
+ page_ranges, page_range_count, print_settings, pdf_print_settings);
+ if (raster)
+ output_doc = CreateRasterPdf(std::move(output_doc), print_settings);
+ if (GetDocumentPageCount(output_doc.get()))
+ buffer = ConvertDocToBuffer(std::move(output_doc));
return buffer;
}
-pp::Buffer_Dev PDFiumPrint::PrintPagesAsPDF(
+ScopedFPDFDocument PDFiumPrint::CreatePrintPdf(
const PP_PrintPageNumberRange_Dev* page_ranges,
uint32_t page_range_count,
const PP_PrintSettings_Dev& print_settings,
@@ -314,59 +331,90 @@ pp::Buffer_Dev PDFiumPrint::PrintPagesAsPDF(
GetPageRangeStringFromRange(page_ranges, page_range_count);
if (!FPDF_ImportPages(output_doc.get(), engine_->doc(),
page_number_str.c_str(), 0)) {
- return pp::Buffer_Dev();
+ return nullptr;
}
- pp::Buffer_Dev buffer;
+ double scale_factor = pdf_print_settings.scale_factor / 100.0;
+ FitContentsToPrintableAreaIfRequired(output_doc.get(), scale_factor,
+ print_settings);
+ if (!FlattenPrintData(output_doc.get()))
+ return nullptr;
+
uint32_t pages_per_sheet = pdf_print_settings.pages_per_sheet;
- uint32_t scale_factor = pdf_print_settings.scale_factor;
- if (ShouldDoNup(pages_per_sheet)) {
- if (FlattenPrintData(output_doc.get()))
- buffer = NupPdfToPdf(output_doc.get(), pages_per_sheet, print_settings);
- } else {
- FitContentsToPrintableAreaIfRequired(output_doc.get(),
- scale_factor / 100.0f, print_settings);
- if (FlattenPrintData(output_doc.get()))
- buffer = GetPrintData(output_doc.get());
+ if (!ShouldDoNup(pages_per_sheet))
+ return output_doc;
+
+ gfx::Size page_size(print_settings.paper_size.width,
+ print_settings.paper_size.height);
+ gfx::Rect printable_area(print_settings.printable_area.point.x,
+ print_settings.printable_area.point.y,
+ print_settings.printable_area.size.width,
+ print_settings.printable_area.size.height);
+ gfx::Rect symmetrical_printable_area =
+ printing::PageSetup::GetSymmetricalPrintableArea(page_size,
+ printable_area);
+ if (symmetrical_printable_area.IsEmpty())
+ return nullptr;
+ return CreateNupPdfDocument(std::move(output_doc), pages_per_sheet, page_size,
+ symmetrical_printable_area);
+}
+
+ScopedFPDFDocument PDFiumPrint::CreateRasterPdf(
+ ScopedFPDFDocument doc,
+ const PP_PrintSettings_Dev& print_settings) {
+ int page_count = GetDocumentPageCount(doc.get());
+ if (page_count == 0)
+ return nullptr;
+
+ ScopedFPDFDocument rasterized_doc(FPDF_CreateNewDocument());
+ DCHECK(rasterized_doc);
+ FPDF_CopyViewerPreferences(rasterized_doc.get(), doc.get());
+
+ for (int i = 0; i < page_count; ++i) {
+ ScopedFPDFPage pdf_page(FPDF_LoadPage(doc.get(), i));
+ if (!pdf_page)
+ return nullptr;
+
+ ScopedFPDFDocument temp_doc =
+ CreateSinglePageRasterPdf(pdf_page.get(), print_settings);
+ if (!temp_doc)
+ return nullptr;
+
+ if (!FPDF_ImportPages(rasterized_doc.get(), temp_doc.get(), "1", i))
+ return nullptr;
}
- return buffer;
+ return rasterized_doc;
}
-FPDF_DOCUMENT PDFiumPrint::CreateSinglePageRasterPdf(
- double source_page_width,
- double source_page_height,
- const PP_PrintSettings_Dev& print_settings,
- PDFiumPage* page_to_print) {
- FPDF_DOCUMENT temp_doc = FPDF_CreateNewDocument();
+ScopedFPDFDocument PDFiumPrint::CreateSinglePageRasterPdf(
+ FPDF_PAGE page_to_print,
+ const PP_PrintSettings_Dev& print_settings) {
+ ScopedFPDFDocument temp_doc(FPDF_CreateNewDocument());
DCHECK(temp_doc);
- const pp::Size& bitmap_size(page_to_print->rect().size());
+ double source_page_width = FPDF_GetPageWidth(page_to_print);
+ double source_page_height = FPDF_GetPageHeight(page_to_print);
- pp::ImageData image =
- pp::ImageData(engine_->GetPluginInstance(),
- PP_IMAGEDATAFORMAT_BGRA_PREMUL, bitmap_size, false);
+ // For computing size in pixels, use a square dpi since the source PDF page
+ // has square DPI.
+ int width_in_pixels =
+ ConvertUnit(source_page_width, kPointsPerInch, print_settings.dpi);
+ int height_in_pixels =
+ ConvertUnit(source_page_height, kPointsPerInch, print_settings.dpi);
- ScopedFPDFBitmap bitmap(
- FPDFBitmap_CreateEx(bitmap_size.width(), bitmap_size.height(),
- FPDFBitmap_BGRx, image.data(), image.stride()));
+ pp::Size bitmap_size(width_in_pixels, height_in_pixels);
+ ScopedFPDFBitmap bitmap(FPDFBitmap_Create(
+ bitmap_size.width(), bitmap_size.height(), /*alpha=*/false));
// Clear the bitmap
FPDFBitmap_FillRect(bitmap.get(), 0, 0, bitmap_size.width(),
bitmap_size.height(), 0xFFFFFFFF);
- pp::Rect page_rect = page_to_print->rect();
- FPDF_RenderPageBitmap(bitmap.get(), page_to_print->GetPrintPage(),
- page_rect.x(), page_rect.y(), page_rect.width(),
- page_rect.height(), print_settings.orientation,
+ FPDF_RenderPageBitmap(bitmap.get(), page_to_print, 0, 0, bitmap_size.width(),
+ bitmap_size.height(), print_settings.orientation,
FPDF_PRINTING | FPDF_NO_CATCH);
- // Draw the forms.
- FPDF_FFLDraw(engine_->form(), bitmap.get(), page_to_print->GetPrintPage(),
- page_rect.x(), page_rect.y(), page_rect.width(),
- page_rect.height(), print_settings.orientation,
- FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH);
-
unsigned char* bitmap_data =
static_cast<unsigned char*>(FPDFBitmap_GetBuffer(bitmap.get()));
double ratio_x = ConvertUnitDouble(bitmap_size.width(), print_settings.dpi,
@@ -376,7 +424,7 @@ FPDF_DOCUMENT PDFiumPrint::CreateSinglePageRasterPdf(
// Add the bitmap to an image object and add the image object to the output
// page.
- FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImageObj(temp_doc);
+ FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImageObj(temp_doc.get());
bool encoded = false;
std::vector<uint8_t> compressed_bitmap_data;
@@ -384,7 +432,7 @@ FPDF_DOCUMENT PDFiumPrint::CreateSinglePageRasterPdf(
// Use quality = 40 as this does not significantly degrade the printed
// document relative to a normal bitmap and provides better compression than
// a higher quality setting.
- const int kQuality = 40;
+ constexpr int kQuality = 40;
SkImageInfo info = SkImageInfo::Make(
FPDFBitmap_GetWidth(bitmap.get()), FPDFBitmap_GetHeight(bitmap.get()),
kBGRA_8888_SkColorType, kOpaque_SkAlphaType);
@@ -394,7 +442,7 @@ FPDF_DOCUMENT PDFiumPrint::CreateSinglePageRasterPdf(
{
ScopedFPDFPage temp_page_holder(
- FPDFPage_New(temp_doc, 0, source_page_width, source_page_height));
+ FPDFPage_New(temp_doc.get(), 0, source_page_width, source_page_height));
FPDF_PAGE temp_page = temp_page_holder.get();
if (encoded) {
FPDF_FILEACCESS file_access = {};
@@ -413,40 +461,10 @@ FPDF_DOCUMENT PDFiumPrint::CreateSinglePageRasterPdf(
FPDFPage_GenerateContent(temp_page);
}
- page_to_print->ClosePrintPage();
return temp_doc;
}
-pp::Buffer_Dev PDFiumPrint::NupPdfToPdf(
- FPDF_DOCUMENT doc,
- uint32_t pages_per_sheet,
- const PP_PrintSettings_Dev& print_settings) {
- DCHECK(doc);
- DCHECK(ShouldDoNup(pages_per_sheet));
-
- PP_Size page_size = print_settings.paper_size;
-
- printing::NupParameters nup_params;
- bool is_landscape = IsSourcePdfLandscape(doc);
- nup_params.SetParameters(pages_per_sheet, is_landscape);
-
- // Import n pages to one.
- bool paper_is_landscape = page_size.width > page_size.height;
- if (nup_params.landscape() != paper_is_landscape)
- std::swap(page_size.width, page_size.height);
-
- ScopedFPDFDocument output_doc_nup(FPDF_ImportNPagesToOne(
- doc, page_size.width, page_size.height, nup_params.num_pages_on_x_axis(),
- nup_params.num_pages_on_y_axis()));
- if (!output_doc_nup)
- return pp::Buffer_Dev();
-
- FitContentsToPrintableAreaIfRequired(output_doc_nup.get(), 1.0f,
- print_settings);
- return GetPrintData(output_doc_nup.get());
-}
-
-bool PDFiumPrint::FlattenPrintData(FPDF_DOCUMENT doc) {
+bool PDFiumPrint::FlattenPrintData(FPDF_DOCUMENT doc) const {
DCHECK(doc);
ScopedSubstFont scoped_subst_font(engine_);
@@ -460,27 +478,4 @@ bool PDFiumPrint::FlattenPrintData(FPDF_DOCUMENT doc) {
return true;
}
-pp::Buffer_Dev PDFiumPrint::GetPrintData(FPDF_DOCUMENT doc) {
- DCHECK(doc);
-
- pp::Buffer_Dev buffer;
- PDFiumMemBufferFileWrite output_file_write;
- if (FPDF_SaveAsCopy(doc, &output_file_write, 0)) {
- size_t size = output_file_write.size();
- buffer = pp::Buffer_Dev(engine_->GetPluginInstance(), size);
- if (!buffer.is_null())
- memcpy(buffer.data(), output_file_write.buffer().data(), size);
- }
- return buffer;
-}
-
-pp::Buffer_Dev PDFiumPrint::GetFlattenedPrintData(FPDF_DOCUMENT doc) {
- DCHECK(doc);
-
- pp::Buffer_Dev buffer;
- if (FlattenPrintData(doc))
- buffer = GetPrintData(doc);
- return buffer;
-}
-
} // namespace chrome_pdf
diff --git a/chromium/pdf/pdfium/pdfium_print.h b/chromium/pdf/pdfium/pdfium_print.h
index 5405a1fc282..e76c5938f26 100644
--- a/chromium/pdf/pdfium/pdfium_print.h
+++ b/chromium/pdf/pdfium/pdfium_print.h
@@ -8,17 +8,21 @@
#include <vector>
#include "base/macros.h"
-#include "ppapi/cpp/dev/buffer_dev.h"
+#include "third_party/pdfium/public/cpp/fpdf_scopers.h"
#include "third_party/pdfium/public/fpdfview.h"
struct PP_PdfPrintSettings_Dev;
struct PP_PrintSettings_Dev;
struct PP_PrintPageNumberRange_Dev;
+namespace gfx {
+class Rect;
+class Size;
+} // namespace gfx
+
namespace chrome_pdf {
class PDFiumEngine;
-class PDFiumPage;
class PDFiumPrint {
public:
@@ -29,16 +33,14 @@ class PDFiumPrint {
const PP_PrintPageNumberRange_Dev* page_ranges,
uint32_t page_range_count);
- pp::Buffer_Dev PrintPagesAsRasterPDF(
- const PP_PrintPageNumberRange_Dev* page_ranges,
- uint32_t page_range_count,
- const PP_PrintSettings_Dev& print_settings,
- const PP_PdfPrintSettings_Dev& pdf_print_settings);
- pp::Buffer_Dev PrintPagesAsPDF(
- const PP_PrintPageNumberRange_Dev* page_ranges,
- uint32_t page_range_count,
- const PP_PrintSettings_Dev& print_settings,
- const PP_PdfPrintSettings_Dev& pdf_print_settings);
+ // Performs N-up PDF generation for |doc| based on |pages_per_sheet|,
+ // |page_size|, and |printable_area|.
+ // On success, returns the N-up version of |doc| as a vector.
+ // On failure, returns an empty vector.
+ static std::vector<uint8_t> CreateNupPdf(ScopedFPDFDocument doc,
+ size_t pages_per_sheet,
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area);
// Check the source doc orientation. Returns true if the doc is landscape.
// For now the orientation of the doc is determined by its first page's
@@ -49,24 +51,33 @@ class PDFiumPrint {
// will not be rotated.
static bool IsSourcePdfLandscape(FPDF_DOCUMENT doc);
+ static void FitContentsToPrintableArea(FPDF_DOCUMENT doc,
+ const gfx::Size& page_size,
+ const gfx::Rect& printable_area);
+
+ std::vector<uint8_t> PrintPagesAsPdf(
+ const PP_PrintPageNumberRange_Dev* page_ranges,
+ uint32_t page_range_count,
+ const PP_PrintSettings_Dev& print_settings,
+ const PP_PdfPrintSettings_Dev& pdf_print_settings,
+ bool raster);
+
private:
- FPDF_DOCUMENT CreateSinglePageRasterPdf(
- double source_page_width,
- double source_page_height,
+ ScopedFPDFDocument CreatePrintPdf(
+ const PP_PrintPageNumberRange_Dev* page_ranges,
+ uint32_t page_range_count,
const PP_PrintSettings_Dev& print_settings,
- PDFiumPage* page_to_print);
-
- // Perform N-up PDF generation from |doc| based on |pages_per_sheet| and
- // the parameters in |print_settings|.
- // On success, the returned buffer contains the N-up version of |doc|.
- // On failure, the returned buffer is empty.
- pp::Buffer_Dev NupPdfToPdf(FPDF_DOCUMENT doc,
- uint32_t pages_per_sheet,
- const PP_PrintSettings_Dev& print_settings);
-
- bool FlattenPrintData(FPDF_DOCUMENT doc);
- pp::Buffer_Dev GetPrintData(FPDF_DOCUMENT doc);
- pp::Buffer_Dev GetFlattenedPrintData(FPDF_DOCUMENT doc);
+ const PP_PdfPrintSettings_Dev& pdf_print_settings);
+
+ ScopedFPDFDocument CreateRasterPdf(
+ ScopedFPDFDocument doc,
+ const PP_PrintSettings_Dev& print_settings);
+
+ ScopedFPDFDocument CreateSinglePageRasterPdf(
+ FPDF_PAGE page_to_print,
+ const PP_PrintSettings_Dev& print_settings);
+
+ bool FlattenPrintData(FPDF_DOCUMENT doc) const;
PDFiumEngine* const engine_;
diff --git a/chromium/pdf/pdfium/pdfium_print_unittest.cc b/chromium/pdf/pdfium/pdfium_print_unittest.cc
new file mode 100644
index 00000000000..57663c10c72
--- /dev/null
+++ b/chromium/pdf/pdfium/pdfium_print_unittest.cc
@@ -0,0 +1,137 @@
+// Copyright 2018 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.
+
+#include "pdf/pdfium/pdfium_print.h"
+
+#include <memory>
+
+#include "base/stl_util.h"
+#include "pdf/pdfium/pdfium_engine.h"
+#include "pdf/pdfium/pdfium_engine_exports.h"
+#include "pdf/pdfium/pdfium_test_base.h"
+#include "pdf/test/test_client.h"
+#include "ppapi/c/dev/ppp_printing_dev.h"
+#include "ppapi/c/private/ppp_pdf.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace chrome_pdf {
+
+using PDFiumPrintTest = PDFiumTestBase;
+using testing::ElementsAre;
+
+namespace {
+
+constexpr PP_Size kUSLetterSize = {612, 792};
+constexpr PP_Rect kUSLetterRect = {{0, 0}, kUSLetterSize};
+
+struct SizeDouble {
+ double width;
+ double height;
+};
+
+using ExpectedDimensions = std::vector<SizeDouble>;
+
+void CheckPdfDimensions(const std::vector<uint8_t>& pdf_data,
+ const ExpectedDimensions& expected_dimensions) {
+ PDFiumEngineExports exports;
+ int page_count;
+ ASSERT_TRUE(exports.GetPDFDocInfo(pdf_data, &page_count, nullptr));
+ ASSERT_GT(page_count, 0);
+ ASSERT_EQ(expected_dimensions.size(), static_cast<size_t>(page_count));
+
+ for (int i = 0; i < page_count; ++i) {
+ double width;
+ double height;
+ ASSERT_TRUE(exports.GetPDFPageSizeByIndex(pdf_data, i, &width, &height));
+ EXPECT_DOUBLE_EQ(expected_dimensions[i].width, width);
+ EXPECT_DOUBLE_EQ(expected_dimensions[i].height, height);
+ }
+}
+
+} // namespace
+
+TEST_F(PDFiumPrintTest, GetPageNumbersFromPrintPageNumberRange) {
+ std::vector<uint32_t> page_numbers;
+
+ {
+ const PP_PrintPageNumberRange_Dev page_ranges[] = {{0, 2}};
+ page_numbers = PDFiumPrint::GetPageNumbersFromPrintPageNumberRange(
+ &page_ranges[0], base::size(page_ranges));
+ EXPECT_THAT(page_numbers, ElementsAre(0, 1, 2));
+ }
+ {
+ const PP_PrintPageNumberRange_Dev page_ranges[] = {{0, 0}, {2, 2}, {4, 5}};
+ page_numbers = PDFiumPrint::GetPageNumbersFromPrintPageNumberRange(
+ &page_ranges[0], base::size(page_ranges));
+ EXPECT_THAT(page_numbers, ElementsAre(0, 2, 4, 5));
+ }
+}
+
+TEST_F(PDFiumPrintTest, Basic) {
+ TestClient client;
+ std::unique_ptr<PDFiumEngine> engine =
+ InitializeEngine(&client, FILE_PATH_LITERAL("hello_world2.pdf"));
+ ASSERT_TRUE(engine);
+
+ PDFiumPrint print(engine.get());
+
+ constexpr PP_PrintSettings_Dev print_settings = {kUSLetterRect,
+ kUSLetterRect,
+ kUSLetterSize,
+ 72,
+ PP_PRINTORIENTATION_NORMAL,
+ PP_PRINTSCALINGOPTION_NONE,
+ PP_FALSE,
+ PP_PRINTOUTPUTFORMAT_PDF};
+ constexpr PP_PdfPrintSettings_Dev pdf_print_settings = {1, 100};
+
+ {
+ // Print 2 pages.
+ const ExpectedDimensions kExpectedDimensions = {{612.0, 792.0},
+ {612.0, 792.0}};
+ const PP_PrintPageNumberRange_Dev page_ranges[] = {{0, 1}};
+ std::vector<uint8_t> pdf_data =
+ print.PrintPagesAsPdf(&page_ranges[0], base::size(page_ranges),
+ print_settings, pdf_print_settings,
+ /*raster=*/false);
+ CheckPdfDimensions(pdf_data, kExpectedDimensions);
+
+ pdf_data = print.PrintPagesAsPdf(&page_ranges[0], base::size(page_ranges),
+ print_settings, pdf_print_settings,
+ /*raster=*/true);
+ CheckPdfDimensions(pdf_data, kExpectedDimensions);
+ }
+ {
+ // Print 1 page.
+ const ExpectedDimensions kExpectedDimensions = {{612.0, 792.0}};
+ const PP_PrintPageNumberRange_Dev page_ranges[] = {{0, 0}};
+ std::vector<uint8_t> pdf_data =
+ print.PrintPagesAsPdf(&page_ranges[0], base::size(page_ranges),
+ print_settings, pdf_print_settings,
+ /*raster=*/false);
+ CheckPdfDimensions(pdf_data, kExpectedDimensions);
+
+ pdf_data = print.PrintPagesAsPdf(&page_ranges[0], base::size(page_ranges),
+ print_settings, pdf_print_settings,
+ /*raster=*/true);
+ CheckPdfDimensions(pdf_data, kExpectedDimensions);
+ }
+ {
+ // Print the other page.
+ const ExpectedDimensions kExpectedDimensions = {{612.0, 792.0}};
+ const PP_PrintPageNumberRange_Dev page_ranges[] = {{1, 1}};
+ std::vector<uint8_t> pdf_data =
+ print.PrintPagesAsPdf(&page_ranges[0], base::size(page_ranges),
+ print_settings, pdf_print_settings,
+ /*raster=*/false);
+ CheckPdfDimensions(pdf_data, kExpectedDimensions);
+
+ pdf_data = print.PrintPagesAsPdf(&page_ranges[0], base::size(page_ranges),
+ print_settings, pdf_print_settings,
+ /*raster=*/true);
+ CheckPdfDimensions(pdf_data, kExpectedDimensions);
+ }
+}
+
+} // namespace chrome_pdf
diff --git a/chromium/pdf/pdfium/pdfium_range.cc b/chromium/pdf/pdfium/pdfium_range.cc
index bec834ff3d9..a89c428bf1c 100644
--- a/chromium/pdf/pdfium/pdfium_range.cc
+++ b/chromium/pdf/pdfium/pdfium_range.cc
@@ -23,6 +23,10 @@ void AdjustForBackwardsRange(int* index, int* count) {
} // namespace
+bool IsIgnorableCharacter(base::char16 c) {
+ return (c == kZeroWidthSpace) || (c == kPDFSoftHyphenMarker);
+}
+
PDFiumRange::PDFiumRange(PDFiumPage* page, int char_index, int char_count)
: page_(page), char_index_(char_index), char_count_(char_count) {
#if DCHECK_IS_ON()
@@ -105,6 +109,8 @@ base::string16 PDFiumRange::GetText() const {
api_string_adapter.Close(written);
}
+ base::EraseIf(rv, [](base::char16 c) { return IsIgnorableCharacter(c); });
+
return rv;
}
diff --git a/chromium/pdf/pdfium/pdfium_range.h b/chromium/pdf/pdfium/pdfium_range.h
index 56b0fcadb8e..80ab37e430c 100644
--- a/chromium/pdf/pdfium/pdfium_range.h
+++ b/chromium/pdf/pdfium/pdfium_range.h
@@ -14,6 +14,14 @@
namespace chrome_pdf {
+constexpr base::char16 kZeroWidthSpace = 0x200B;
+constexpr base::char16 kPDFSoftHyphenMarker = 0xFFFE;
+
+// Helper for identifying characters that PDFium outputs, via FPDFText_GetText,
+// that have special meaning, but should not be included in things like copied
+// text or when running find.
+bool IsIgnorableCharacter(base::char16 c);
+
// Describes location of a string of characters.
class PDFiumRange {
public:
diff --git a/chromium/pdf/pdfium/pdfium_test_base.cc b/chromium/pdf/pdfium/pdfium_test_base.cc
new file mode 100644
index 00000000000..4acdcdddc1c
--- /dev/null
+++ b/chromium/pdf/pdfium/pdfium_test_base.cc
@@ -0,0 +1,70 @@
+// Copyright 2018 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.
+
+#include "pdf/pdfium/pdfium_test_base.h"
+
+#include <memory>
+
+#include "pdf/pdfium/pdfium_engine.h"
+#include "pdf/test/test_client.h"
+#include "pdf/test/test_document_loader.h"
+
+namespace chrome_pdf {
+
+namespace {
+
+const base::FilePath::CharType* g_test_pdf_name;
+
+std::unique_ptr<DocumentLoader> CreateTestDocumentLoader(
+ DocumentLoader::Client* client) {
+ return std::make_unique<TestDocumentLoader>(client, g_test_pdf_name);
+}
+
+} // namespace
+
+PDFiumTestBase::PDFiumTestBase() = default;
+
+PDFiumTestBase::~PDFiumTestBase() = default;
+
+void PDFiumTestBase::SetUp() {
+ InitializePDFium();
+}
+
+void PDFiumTestBase::TearDown() {
+ PDFiumEngine::SetCreateDocumentLoaderFunctionForTesting(nullptr);
+ g_test_pdf_name = nullptr;
+ FPDF_DestroyLibrary();
+}
+
+std::unique_ptr<PDFiumEngine> PDFiumTestBase::InitializeEngine(
+ TestClient* client,
+ const base::FilePath::CharType* pdf_name) {
+ SetDocumentForTest(pdf_name);
+ pp::URLLoader dummy_loader;
+ auto engine = std::make_unique<PDFiumEngine>(client, true);
+ if (!engine->New("https://chromium.org/dummy.pdf", "") ||
+ !engine->HandleDocumentLoad(dummy_loader)) {
+ return nullptr;
+ }
+ return engine;
+}
+
+void PDFiumTestBase::SetDocumentForTest(
+ const base::FilePath::CharType* pdf_name) {
+ DCHECK(!g_test_pdf_name);
+ g_test_pdf_name = pdf_name;
+ PDFiumEngine::SetCreateDocumentLoaderFunctionForTesting(
+ &CreateTestDocumentLoader);
+}
+
+void PDFiumTestBase::InitializePDFium() {
+ FPDF_LIBRARY_CONFIG config;
+ config.version = 2;
+ config.m_pUserFontPaths = nullptr;
+ config.m_pIsolate = nullptr;
+ config.m_v8EmbedderSlot = 0;
+ FPDF_InitLibraryWithConfig(&config);
+}
+
+} // namespace chrome_pdf
diff --git a/chromium/pdf/pdfium/pdfium_test_base.h b/chromium/pdf/pdfium/pdfium_test_base.h
new file mode 100644
index 00000000000..d7956f26d64
--- /dev/null
+++ b/chromium/pdf/pdfium/pdfium_test_base.h
@@ -0,0 +1,47 @@
+// Copyright 2018 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.
+
+#ifndef PDF_PDFIUM_PDFIUM_TEST_BASE_H_
+#define PDF_PDFIUM_PDFIUM_TEST_BASE_H_
+
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_pdf {
+
+class PDFiumEngine;
+class TestClient;
+
+class PDFiumTestBase : public testing::Test {
+ public:
+ PDFiumTestBase();
+ ~PDFiumTestBase() override;
+
+ protected:
+ // testing::Test:
+ void SetUp() override;
+ void TearDown() override;
+
+ // Initializes a PDFiumEngine for use in testing with |client|. Loads a PDF
+ // named |pdf_name|.See TestDocumentLoader for more info about |pdf_name|.
+ std::unique_ptr<PDFiumEngine> InitializeEngine(
+ TestClient* client,
+ const base::FilePath::CharType* pdf_name);
+
+ private:
+ // Sets the PDF to load for a test. This must be called for tests that use
+ // TestDocumentLoader. See TestDocumentLoader for more info.
+ void SetDocumentForTest(const base::FilePath::CharType* pdf_name);
+
+ void InitializePDFium();
+
+ DISALLOW_COPY_AND_ASSIGN(PDFiumTestBase);
+};
+
+} // namespace chrome_pdf
+
+#endif // PDF_PDFIUM_PDFIUM_TEST_BASE_H_