1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "pdf/pdf_view_web_plugin.h"
15 #include "base/containers/span.h"
16 #include "base/location.h"
17 #include "base/memory/raw_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_piece.h"
21 #include "base/task/single_thread_task_runner.h"
22 #include "base/test/bind.h"
23 #include "base/test/scoped_feature_list.h"
24 #include "base/test/values_test_util.h"
25 #include "base/time/time.h"
26 #include "base/values.h"
27 #include "cc/paint/paint_canvas.h"
28 #include "cc/test/pixel_comparator.h"
29 #include "cc/test/pixel_test_utils.h"
30 #include "mojo/public/cpp/bindings/associated_receiver.h"
31 #include "mojo/public/cpp/bindings/associated_remote.h"
32 #include "net/cookies/site_for_cookies.h"
33 #include "pdf/accessibility_structs.h"
34 #include "pdf/buildflags.h"
35 #include "pdf/content_restriction.h"
36 #include "pdf/document_layout.h"
37 #include "pdf/mojom/pdf.mojom.h"
38 #include "pdf/paint_ready_rect.h"
39 #include "pdf/pdf_accessibility_data_handler.h"
40 #include "pdf/pdf_accessibility_image_fetcher.h"
41 #include "pdf/pdf_features.h"
42 #include "pdf/test/mock_web_associated_url_loader.h"
43 #include "pdf/test/test_helpers.h"
44 #include "pdf/test/test_pdfium_engine.h"
45 #include "printing/metafile_skia.h"
46 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
47 #include "testing/gmock/include/gmock/gmock.h"
48 #include "testing/gtest/include/gtest/gtest.h"
49 #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
50 #include "third_party/blink/public/common/input/web_input_event.h"
51 #include "third_party/blink/public/common/input/web_keyboard_event.h"
52 #include "third_party/blink/public/common/input/web_mouse_event.h"
53 #include "third_party/blink/public/common/loader/http_body_element_type.h"
54 #include "third_party/blink/public/platform/web_data.h"
55 #include "third_party/blink/public/platform/web_http_body.h"
56 #include "third_party/blink/public/platform/web_http_header_visitor.h"
57 #include "third_party/blink/public/platform/web_input_event_result.h"
58 #include "third_party/blink/public/platform/web_string.h"
59 #include "third_party/blink/public/platform/web_text_input_type.h"
60 #include "third_party/blink/public/platform/web_url.h"
61 #include "third_party/blink/public/platform/web_url_request.h"
62 #include "third_party/blink/public/platform/web_url_response.h"
63 #include "third_party/blink/public/web/web_associated_url_loader.h"
64 #include "third_party/blink/public/web/web_associated_url_loader_client.h"
65 #include "third_party/blink/public/web/web_plugin_container.h"
66 #include "third_party/blink/public/web/web_plugin_params.h"
67 #include "third_party/blink/public/web/web_print_params.h"
68 #include "third_party/skia/include/core/SkBitmap.h"
69 #include "third_party/skia/include/core/SkCanvas.h"
70 #include "third_party/skia/include/core/SkColor.h"
71 #include "third_party/skia/include/core/SkRefCnt.h"
72 #include "third_party/skia/include/core/SkSurface.h"
73 #include "ui/base/cursor/cursor.h"
74 #include "ui/events/blink/blink_event_util.h"
75 #include "ui/events/keycodes/dom/dom_code.h"
76 #include "ui/events/keycodes/dom/dom_key.h"
77 #include "ui/gfx/canvas.h"
78 #include "ui/gfx/geometry/point.h"
79 #include "ui/gfx/geometry/point_f.h"
80 #include "ui/gfx/geometry/rect.h"
81 #include "ui/gfx/geometry/size.h"
82 #include "ui/gfx/geometry/skia_conversions.h"
83 #include "ui/gfx/geometry/vector2d_f.h"
84 #include "ui/gfx/range/range.h"
85 #include "ui/latency/latency_info.h"
88 namespace chrome_pdf {
92 using ::testing::AnyNumber;
93 using ::testing::ElementsAre;
94 using ::testing::ElementsAreArray;
96 using ::testing::InSequence;
97 using ::testing::Invoke;
98 using ::testing::IsEmpty;
99 using ::testing::IsFalse;
100 using ::testing::IsTrue;
101 using ::testing::MockFunction;
102 using ::testing::NiceMock;
103 using ::testing::Pointwise;
104 using ::testing::Return;
105 using ::testing::SaveArg;
106 using ::testing::SizeIs;
108 // `kCanvasSize` needs to be big enough to hold plugin's snapshots during
110 constexpr gfx::Size kCanvasSize(100, 100);
112 // Note: Make sure `kDefaultColor` is different from `kPaintColor` and the
113 // plugin's background color. This will help identify bitmap changes after
115 constexpr SkColor kDefaultColor = SK_ColorGREEN;
117 constexpr SkColor kPaintColor = SK_ColorRED;
120 // The plugin container's device scale.
123 // The window area in CSS pixels.
124 gfx::Rect window_rect;
126 // The target painting area on the canvas in CSS pixels.
127 gfx::Rect paint_rect;
129 // The expected clipped area to be filled with paint color. The clipped area
130 // should be the intersection of `paint_rect` and `window_rect`.
131 gfx::Rect expected_clipped_rect;
134 MATCHER(SearchStringResultEq, "") {
135 PDFEngine::Client::SearchStringResult l = std::get<0>(arg);
136 PDFEngine::Client::SearchStringResult r = std::get<1>(arg);
137 return l.start_index == r.start_index && l.length == r.length;
140 MATCHER_P(IsExpectedImeKeyEvent, expected_text, "") {
141 if (arg.GetType() != blink::WebInputEvent::Type::kChar)
144 const auto& event = static_cast<const blink::WebKeyboardEvent&>(arg);
145 return event.GetModifiers() == blink::WebInputEvent::kNoModifiers &&
146 event.windows_key_code == expected_text[0] &&
147 event.native_key_code == expected_text[0] &&
148 event.dom_code == static_cast<int>(ui::DomCode::NONE) &&
149 event.dom_key == ui::DomKey::NONE && !event.is_system_key &&
150 !event.is_browser_shortcut && event.text == expected_text &&
151 event.unmodified_text == expected_text;
154 base::Value::Dict ParseMessage(base::StringPiece json) {
155 return std::move(base::test::ParseJson(json).GetDict());
158 // Generates the expected `SkBitmap` with `paint_color` filled in the expected
159 // clipped area and `kDefaultColor` as the background color.
160 SkBitmap GenerateExpectedBitmapForPaint(const gfx::Rect& expected_clipped_rect,
161 SkColor paint_color) {
162 sk_sp<SkSurface> expected_surface =
163 CreateSkiaSurfaceForTesting(kCanvasSize, kDefaultColor);
164 expected_surface->getCanvas()->clipIRect(
165 gfx::RectToSkIRect(expected_clipped_rect));
166 expected_surface->getCanvas()->clear(paint_color);
168 SkBitmap expected_bitmap;
169 expected_surface->makeImageSnapshot()->asLegacyBitmap(&expected_bitmap);
170 return expected_bitmap;
173 class MockHeaderVisitor : public blink::WebHTTPHeaderVisitor {
177 (const blink::WebString&, const blink::WebString&),
181 class MockPdfAccessibilityDataHandler : public PdfAccessibilityDataHandler {
183 // PdfAccessibilityDataHandler:
185 SetAccessibilityViewportInfo,
186 (AccessibilityViewportInfo),
189 SetAccessibilityDocInfo,
190 (AccessibilityDocInfo),
193 SetAccessibilityPageInfo,
194 (AccessibilityPageInfo,
195 std::vector<AccessibilityTextRunInfo>,
196 std::vector<AccessibilityCharInfo>,
197 AccessibilityPageObjects),
201 class FakePdfViewWebPluginClient : public PdfViewWebPlugin::Client {
203 FakePdfViewWebPluginClient() {
204 ON_CALL(*this, CreateAssociatedURLLoader).WillByDefault([]() {
205 auto associated_loader =
206 std::make_unique<NiceMock<MockWebAssociatedURLLoader>>();
207 ON_CALL(*associated_loader, LoadAsynchronously)
208 .WillByDefault([](const blink::WebURLRequest& /*request*/,
209 blink::WebAssociatedURLLoaderClient* client) {
210 // TODO(crbug.com/1322928): Must trigger callback to free
212 client->DidReceiveResponse(blink::WebURLResponse());
213 client->DidFinishLoading();
215 return associated_loader;
217 ON_CALL(*this, GetEmbedderOriginString)
219 Return("chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/"));
220 ON_CALL(*this, HasFrame).WillByDefault(Return(true));
223 // PdfViewWebPlugin::Client:
224 MOCK_METHOD(std::unique_ptr<base::Value>,
226 (v8::Local<v8::Value>, v8::Local<v8::Context>),
229 MOCK_METHOD(base::WeakPtr<Client>, GetWeakPtr, (), (override));
231 MOCK_METHOD(std::unique_ptr<PDFiumEngine>,
233 (PDFEngine::Client*, PDFiumFormFiller::ScriptOption),
238 (blink::WebPluginContainer*),
240 MOCK_METHOD(blink::WebPluginContainer*, PluginContainer, (), (override));
242 MOCK_METHOD(net::SiteForCookies, SiteForCookies, (), (const override));
244 MOCK_METHOD(blink::WebURL,
246 (const blink::WebString&),
249 MOCK_METHOD(void, PostMessage, (base::Value::Dict), (override));
251 MOCK_METHOD(void, Invalidate, (), (override));
254 RequestTouchEventType,
255 (blink::WebPluginContainer::TouchEventRequestType),
258 MOCK_METHOD(void, ReportFindInPageMatchCount, (int, int, bool), (override));
260 MOCK_METHOD(void, ReportFindInPageSelection, (int, int, bool), (override));
263 ReportFindInPageTickmarks,
264 (const std::vector<gfx::Rect>&),
267 MOCK_METHOD(float, DeviceScaleFactor, (), (override));
269 MOCK_METHOD(gfx::PointF, GetScrollPosition, (), (override));
271 MOCK_METHOD(void, UsePluginAsFindHandler, (), (override));
274 SetReferrerForRequest,
275 (blink::WebURLRequest&, const blink::WebURL&),
278 MOCK_METHOD(void, Alert, (const blink::WebString&), (override));
280 MOCK_METHOD(bool, Confirm, (const blink::WebString&), (override));
282 MOCK_METHOD(blink::WebString,
284 (const blink::WebString&, const blink::WebString&),
288 TextSelectionChanged,
289 (const blink::WebString&, uint32_t, const gfx::Range&),
292 MOCK_METHOD(std::unique_ptr<blink::WebAssociatedURLLoader>,
293 CreateAssociatedURLLoader,
294 (const blink::WebAssociatedURLLoaderOptions&),
297 MOCK_METHOD(void, UpdateTextInputState, (), (override));
299 MOCK_METHOD(void, UpdateSelectionBounds, (), (override));
301 MOCK_METHOD(std::string, GetEmbedderOriginString, (), (override));
303 MOCK_METHOD(bool, HasFrame, (), (const override));
305 MOCK_METHOD(void, DidStartLoading, (), (override));
306 MOCK_METHOD(void, DidStopLoading, (), (override));
308 MOCK_METHOD(void, RecordComputedAction, (const std::string&), (override));
310 MOCK_METHOD(std::unique_ptr<PdfAccessibilityDataHandler>,
311 CreateAccessibilityDataHandler,
312 (PdfAccessibilityActionHandler*, PdfAccessibilityImageFetcher*),
316 class FakePdfService : public pdf::mojom::PdfService {
320 (mojo::PendingRemote<pdf::mojom::PdfListener>),
322 MOCK_METHOD(void, UpdateContentRestrictions, (int32_t), (override));
323 MOCK_METHOD(void, HasUnsupportedFeature, (), (override));
326 (const GURL&, network::mojom::ReferrerPolicy),
330 (const gfx::PointF&, int32_t, const gfx::PointF&, int32_t),
332 MOCK_METHOD(void, SetPluginCanSave, (bool), (override));
337 class PdfViewWebPluginWithoutInitializeTest
338 : public testing::TestWithParam<bool> {
340 // Custom deleter for `plugin_`. PdfViewWebPlugin must be destroyed by
341 // PdfViewWebPlugin::Destroy() instead of its destructor.
342 struct PluginDeleter {
343 void operator()(PdfViewWebPlugin* ptr) { ptr->Destroy(); }
346 static void AddToPluginParams(base::StringPiece name,
347 base::StringPiece value,
348 blink::WebPluginParams& params) {
349 params.attribute_names.push_back(blink::WebString::FromUTF8(name));
350 params.attribute_values.push_back(blink::WebString::FromUTF8(value));
353 void SetUpPlugin(base::StringPiece document_url,
354 const blink::WebPluginParams& params) {
355 auto client = std::make_unique<NiceMock<FakePdfViewWebPluginClient>>();
356 client_ptr_ = client.get();
358 ON_CALL(*client_ptr_, CompleteURL)
359 .WillByDefault([parsed_document_url = GURL(document_url)](
360 const blink::WebString& partial_url) {
361 return parsed_document_url.Resolve(partial_url.Utf8());
363 ON_CALL(*client_ptr_, CreateEngine)
364 .WillByDefault([this](
365 PDFEngine::Client* client,
366 PDFiumFormFiller::ScriptOption /*script_option*/) {
367 auto engine = std::make_unique<NiceMock<TestPDFiumEngine>>(client);
368 engine_ptr_ = engine.get();
371 ON_CALL(*client_ptr_, CreateAccessibilityDataHandler)
372 .WillByDefault([this]() {
374 std::make_unique<NiceMock<MockPdfAccessibilityDataHandler>>();
375 accessibility_data_handler_ptr_ = handler.get();
381 std::unique_ptr<PdfViewWebPlugin, PluginDeleter>(new PdfViewWebPlugin(
383 mojo::AssociatedRemote<pdf::mojom::PdfService>(
384 pdf_receiver_.BindNewEndpointAndPassDedicatedRemote()),
388 void SetUpPluginWithUrl(const std::string& url) {
389 blink::WebPluginParams params;
390 AddToPluginParams("src", url, params);
391 SetUpPluginParams(params);
393 SetUpPlugin(url, params);
396 // Allows derived classes to customize plugin parameters within
397 // `SetUpPluginWithUrl()`.
398 virtual void SetUpPluginParams(blink::WebPluginParams& params) {}
400 // Allows derived classes to customize `client_ptr_` within `SetUpPlugin()`.
401 virtual void SetUpClient() {}
403 void ExpectUpdateTextInputState(
404 blink::WebTextInputType expected_text_input_type) {
405 EXPECT_CALL(*client_ptr_, UpdateTextInputState)
406 .WillOnce([this, expected_text_input_type]() {
407 EXPECT_EQ(expected_text_input_type,
408 plugin_->GetPluginTextInputType());
412 void OnMessageWithEngineUpdate(const base::Value::Dict& message) {
413 // New engine will be created making this unowned reference stale.
414 engine_ptr_ = nullptr;
415 plugin_->OnMessage(message);
418 NiceMock<FakePdfService> pdf_service_;
419 mojo::AssociatedReceiver<pdf::mojom::PdfService> pdf_receiver_{&pdf_service_};
421 // Must outlive raw_ptrs below.
422 std::unique_ptr<PdfViewWebPlugin, PluginDeleter> plugin_;
424 raw_ptr<FakePdfViewWebPluginClient> client_ptr_;
425 raw_ptr<TestPDFiumEngine> engine_ptr_;
426 raw_ptr<MockPdfAccessibilityDataHandler> accessibility_data_handler_ptr_;
429 class PdfViewWebPluginTest : public PdfViewWebPluginWithoutInitializeTest {
431 static constexpr char kPdfUrl[] = "http://localhost/example.pdf";
433 void SetUp() override {
434 SetUpPluginWithUrl(kPdfUrl);
436 EXPECT_TRUE(plugin_->InitializeForTesting());
439 void SetDocumentDimensions(const gfx::Size& dimensions) {
440 EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout)
441 .WillRepeatedly(Return(dimensions));
442 SendViewportMessage(/*zoom=*/1.0);
445 void SendViewportMessage(double zoom) {
446 base::Value::Dict message = ParseMessage(R"({
448 "userInitiated": false,
452 "defaultPageOrientation": 0,
453 "twoUpViewEnabled": false,
459 message.Set("zoom", zoom);
460 plugin_->OnMessage(message);
463 void UpdatePluginGeometry(float device_scale, const gfx::Rect& window_rect) {
464 UpdatePluginGeometryWithoutWaiting(device_scale, window_rect);
466 // Waits for main thread callback scheduled by `PaintManager`.
467 base::RunLoop run_loop;
468 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
469 FROM_HERE, run_loop.QuitClosure());
473 void UpdatePluginGeometryWithoutWaiting(float device_scale,
474 const gfx::Rect& window_rect) {
475 // The plugin container's device scale must be set before calling
477 EXPECT_CALL(*client_ptr_, DeviceScaleFactor)
478 .WillRepeatedly(Return(device_scale));
479 plugin_->UpdateGeometry(window_rect, window_rect, window_rect,
480 /*is_visible=*/true);
483 void TestUpdateGeometrySetsPluginRect(float device_scale,
484 const gfx::Rect& window_rect,
485 float expected_device_scale,
486 const gfx::Rect& expected_plugin_rect) {
487 UpdatePluginGeometryWithoutWaiting(device_scale, window_rect);
488 EXPECT_EQ(expected_device_scale, plugin_->GetDeviceScaleForTesting())
489 << "Device scale comparison failure at device scale of "
491 EXPECT_EQ(expected_plugin_rect, plugin_->GetPluginRectForTesting())
492 << "Plugin rect comparison failure at device scale of " << device_scale
493 << ", window rect of " << window_rect.ToString();
496 void TestPaintEmptySnapshots(float device_scale,
497 const gfx::Rect& window_rect,
498 const gfx::Rect& paint_rect,
499 const gfx::Rect& expected_clipped_rect) {
500 UpdatePluginGeometryWithoutWaiting(device_scale, window_rect);
501 canvas_.DrawColor(kDefaultColor);
503 plugin_->Paint(canvas_.sk_canvas(), paint_rect);
505 // Expect the clipped area on canvas to be filled with plugin's background
507 SkBitmap expected_bitmap = GenerateExpectedBitmapForPaint(
508 expected_clipped_rect, plugin_->GetBackgroundColor());
509 EXPECT_TRUE(cc::MatchesBitmap(canvas_.GetBitmap(), expected_bitmap,
510 cc::ExactPixelComparator()))
511 << "Failure at device scale of " << device_scale << ", window rect of "
512 << window_rect.ToString();
515 void TestPaintSnapshots(float device_scale,
516 const gfx::Rect& window_rect,
517 const gfx::Rect& paint_rect,
518 const gfx::Rect& expected_clipped_rect) {
519 UpdatePluginGeometry(device_scale, window_rect);
520 canvas_.DrawColor(kDefaultColor);
522 // Paint the plugin with `kPaintColor`.
523 plugin_->UpdateSnapshot(CreateSkiaImageForTesting(
524 plugin_->GetPluginRectForTesting().size(), kPaintColor));
525 plugin_->Paint(canvas_.sk_canvas(), paint_rect);
527 // Expect the clipped area on canvas to be filled with `kPaintColor`.
528 SkBitmap expected_bitmap =
529 GenerateExpectedBitmapForPaint(expected_clipped_rect, kPaintColor);
530 EXPECT_TRUE(cc::MatchesBitmap(canvas_.GetBitmap(), expected_bitmap,
531 cc::ExactPixelComparator()))
532 << "Failure at device scale of " << device_scale << ", window rect of "
533 << window_rect.ToString();
536 // Provides the cc::PaintCanvas for painting.
537 gfx::Canvas canvas_{kCanvasSize, /*image_scale=*/1.0f, /*is_opaque=*/true};
540 class PdfViewWebPluginFullFrameTest : public PdfViewWebPluginTest {
542 void SetUpPluginParams(blink::WebPluginParams& params) override {
543 AddToPluginParams("full-frame", "full-frame", params);
547 TEST_F(PdfViewWebPluginWithoutInitializeTest, Initialize) {
548 SetUpPluginWithUrl("http://localhost/example.pdf");
550 EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader)
551 .WillOnce([](const blink::WebAssociatedURLLoaderOptions& options) {
552 EXPECT_TRUE(options.grant_universal_access);
554 auto associated_loader =
555 std::make_unique<NiceMock<MockWebAssociatedURLLoader>>();
556 EXPECT_CALL(*associated_loader, LoadAsynchronously)
557 .WillOnce([](const blink::WebURLRequest& request,
558 blink::WebAssociatedURLLoaderClient* client) {
559 EXPECT_EQ("http://localhost/example.pdf",
560 request.Url().GetString().Utf8());
561 EXPECT_EQ("GET", request.HttpMethod().Utf8());
562 EXPECT_TRUE(request.HttpBody().IsNull());
564 NiceMock<MockHeaderVisitor> header_visitor;
565 EXPECT_CALL(header_visitor, VisitHeader).Times(0);
566 request.VisitHttpHeaderFields(&header_visitor);
568 EXPECT_FALSE(client->WillFollowRedirect(blink::WebURL(),
569 blink::WebURLResponse()));
570 client->DidReceiveResponse(blink::WebURLResponse());
571 client->DidFinishLoading();
573 return associated_loader;
575 EXPECT_CALL(*client_ptr_, SetReferrerForRequest).Times(0);
577 EXPECT_TRUE(plugin_->InitializeForTesting());
580 TEST_F(PdfViewWebPluginWithoutInitializeTest, InitializeWithEmptyUrl) {
581 SetUpPluginWithUrl("");
583 EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader).Times(0);
585 EXPECT_FALSE(plugin_->InitializeForTesting());
588 TEST_F(PdfViewWebPluginWithoutInitializeTest, InitializeForPrintPreview) {
589 SetUpPluginWithUrl("about:blank");
591 EXPECT_CALL(*client_ptr_, GetEmbedderOriginString)
592 .WillRepeatedly(Return("chrome://print/"));
593 EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader).Times(0);
595 EXPECT_TRUE(plugin_->InitializeForTesting());
598 TEST_F(PdfViewWebPluginTest, CreateUrlLoader) {
599 EXPECT_CALL(*client_ptr_, DidStartLoading).Times(0);
600 EXPECT_CALL(pdf_service_, UpdateContentRestrictions).Times(0);
601 plugin_->CreateUrlLoader();
603 EXPECT_EQ(PdfViewWebPlugin::DocumentLoadState::kLoading,
604 plugin_->document_load_state_for_testing());
605 pdf_receiver_.FlushForTesting();
608 TEST_F(PdfViewWebPluginFullFrameTest, CreateUrlLoader) {
609 EXPECT_CALL(*client_ptr_, DidStartLoading);
610 EXPECT_CALL(pdf_service_,
611 UpdateContentRestrictions(kContentRestrictionSave |
612 kContentRestrictionPrint));
613 plugin_->CreateUrlLoader();
615 EXPECT_EQ(PdfViewWebPlugin::DocumentLoadState::kLoading,
616 plugin_->document_load_state_for_testing());
617 pdf_receiver_.FlushForTesting();
620 TEST_F(PdfViewWebPluginFullFrameTest, CreateUrlLoaderMultipleTimes) {
621 plugin_->CreateUrlLoader();
623 EXPECT_CALL(*client_ptr_, DidStartLoading).Times(0);
624 plugin_->CreateUrlLoader();
627 TEST_F(PdfViewWebPluginFullFrameTest, CreateUrlLoaderAfterDocumentLoadFailed) {
628 plugin_->CreateUrlLoader();
629 plugin_->DocumentLoadFailed();
631 EXPECT_CALL(*client_ptr_, DidStartLoading);
632 plugin_->CreateUrlLoader();
635 TEST_F(PdfViewWebPluginTest, DocumentLoadComplete) {
636 plugin_->CreateUrlLoader();
638 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadSuccess"));
639 EXPECT_CALL(*client_ptr_, PostMessage);
640 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
641 "type": "formFocusChange",
644 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
645 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
646 "type": "printPreviewLoaded",
649 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
651 EXPECT_CALL(*client_ptr_, DidStopLoading).Times(0);
652 EXPECT_CALL(pdf_service_, UpdateContentRestrictions).Times(0);
653 plugin_->DocumentLoadComplete();
655 EXPECT_EQ(PdfViewWebPlugin::DocumentLoadState::kComplete,
656 plugin_->document_load_state_for_testing());
657 pdf_receiver_.FlushForTesting();
660 TEST_F(PdfViewWebPluginFullFrameTest, DocumentLoadComplete) {
661 // Must flush IPCs after `CreateUrlLoader()` in full-frame mode, otherwise
662 // there's an unexpected `UpdateContentRestrictions()` call (see the
663 // `PdfViewWebPluginFullFrameTest.CreateUrlLoader` test).
664 plugin_->CreateUrlLoader();
665 pdf_receiver_.FlushForTesting();
667 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadSuccess"));
668 EXPECT_CALL(*client_ptr_, PostMessage);
669 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
670 "type": "formFocusChange",
673 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
674 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
675 "type": "printPreviewLoaded",
678 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
680 EXPECT_CALL(*client_ptr_, DidStopLoading);
681 EXPECT_CALL(pdf_service_, UpdateContentRestrictions(kContentRestrictionPrint |
682 kContentRestrictionPaste |
683 kContentRestrictionCut |
684 kContentRestrictionCopy));
685 plugin_->DocumentLoadComplete();
687 EXPECT_EQ(PdfViewWebPlugin::DocumentLoadState::kComplete,
688 plugin_->document_load_state_for_testing());
689 pdf_receiver_.FlushForTesting();
692 TEST_F(PdfViewWebPluginTest, DocumentLoadFailed) {
693 plugin_->CreateUrlLoader();
695 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadFailure"));
696 EXPECT_CALL(*client_ptr_, DidStopLoading).Times(0);
697 plugin_->DocumentLoadFailed();
699 EXPECT_EQ(PdfViewWebPlugin::DocumentLoadState::kFailed,
700 plugin_->document_load_state_for_testing());
703 TEST_F(PdfViewWebPluginFullFrameTest, DocumentLoadFailed) {
704 plugin_->CreateUrlLoader();
706 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadFailure"));
707 EXPECT_CALL(*client_ptr_, DidStopLoading);
708 plugin_->DocumentLoadFailed();
710 EXPECT_EQ(PdfViewWebPlugin::DocumentLoadState::kFailed,
711 plugin_->document_load_state_for_testing());
714 TEST_F(PdfViewWebPluginTest, DocumentHasUnsupportedFeature) {
715 EXPECT_CALL(*client_ptr_, RecordComputedAction).Times(AnyNumber());
716 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature1"));
717 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature2"));
719 // `HasUnsupportedFeature()` is not called if the viewer is not full-frame.
720 EXPECT_CALL(pdf_service_, HasUnsupportedFeature).Times(0);
722 plugin_->DocumentHasUnsupportedFeature("feature1");
723 plugin_->DocumentHasUnsupportedFeature("feature2");
725 pdf_receiver_.FlushForTesting();
728 TEST_F(PdfViewWebPluginTest, DocumentHasUnsupportedFeatureWithRepeatedFeature) {
729 // Metrics should only be recorded once per feature.
730 EXPECT_CALL(*client_ptr_, RecordComputedAction).Times(AnyNumber());
731 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature"));
733 // `HasUnsupportedFeature()` is not called if the viewer is not full-frame.
734 EXPECT_CALL(pdf_service_, HasUnsupportedFeature).Times(0);
736 plugin_->DocumentHasUnsupportedFeature("feature");
737 plugin_->DocumentHasUnsupportedFeature("feature");
739 pdf_receiver_.FlushForTesting();
742 TEST_F(PdfViewWebPluginFullFrameTest, DocumentHasUnsupportedFeature) {
743 EXPECT_CALL(*client_ptr_, RecordComputedAction).Times(AnyNumber());
744 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature1"));
745 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature2"));
747 // `HasUnsupportedFeature()` is called once for all features.
748 EXPECT_CALL(pdf_service_, HasUnsupportedFeature);
750 plugin_->DocumentHasUnsupportedFeature("feature1");
751 plugin_->DocumentHasUnsupportedFeature("feature2");
753 pdf_receiver_.FlushForTesting();
756 TEST_F(PdfViewWebPluginFullFrameTest,
757 DocumentHasUnsupportedFeatureWithRepeatedFeature) {
758 // Metrics should only be recorded once per feature.
759 EXPECT_CALL(*client_ptr_, RecordComputedAction).Times(AnyNumber());
760 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature"));
762 // `HasUnsupportedFeature()` is called once for all features.
763 EXPECT_CALL(pdf_service_, HasUnsupportedFeature);
765 plugin_->DocumentHasUnsupportedFeature("feature");
766 plugin_->DocumentHasUnsupportedFeature("feature");
768 pdf_receiver_.FlushForTesting();
771 TEST_F(PdfViewWebPluginTest, DocumentLoadProgress) {
772 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
773 "type": "loadProgress",
776 plugin_->DocumentLoadProgress(10, 200);
779 TEST_F(PdfViewWebPluginTest, DocumentLoadProgressIgnoreSmall) {
780 plugin_->DocumentLoadProgress(2, 100);
782 EXPECT_CALL(*client_ptr_, PostMessage).Times(0);
783 plugin_->DocumentLoadProgress(3, 100);
786 TEST_F(PdfViewWebPluginTest, DocumentLoadProgressMultipleSmall) {
787 plugin_->DocumentLoadProgress(2, 100);
789 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
790 "type": "loadProgress",
793 plugin_->DocumentLoadProgress(3, 100);
794 plugin_->DocumentLoadProgress(4, 100);
797 TEST_F(PdfViewWebPluginTest, EnableAccessibilityBeforeDocumentLoadComplete) {
798 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
800 plugin_->EnableAccessibility();
802 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
803 plugin_->CreateUrlLoader();
804 plugin_->DocumentLoadComplete();
807 TEST_F(PdfViewWebPluginTest,
808 EnableAccessibilityBeforeDocumentLoadCompleteRepeated) {
809 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
811 plugin_->EnableAccessibility();
812 plugin_->EnableAccessibility();
814 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
815 plugin_->CreateUrlLoader();
816 plugin_->DocumentLoadComplete();
819 TEST_F(PdfViewWebPluginTest, EnableAccessibilityAfterDocumentLoadComplete) {
820 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
822 plugin_->CreateUrlLoader();
823 plugin_->DocumentLoadComplete();
825 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
826 plugin_->EnableAccessibility();
829 TEST_F(PdfViewWebPluginTest,
830 EnableAccessibilityAfterDocumentLoadCompleteRepeated) {
831 plugin_->CreateUrlLoader();
832 plugin_->DocumentLoadComplete();
833 plugin_->EnableAccessibility();
835 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
837 plugin_->EnableAccessibility();
840 TEST_F(PdfViewWebPluginTest,
841 LoadOrReloadAccessibilityBeforeDocumentLoadComplete) {
842 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
844 plugin_->LoadOrReloadAccessibility();
846 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
847 plugin_->CreateUrlLoader();
848 plugin_->DocumentLoadComplete();
851 TEST_F(PdfViewWebPluginTest,
852 LoadOrReloadAccessibilityBeforeDocumentLoadCompleteRepeated) {
853 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
855 plugin_->LoadOrReloadAccessibility();
856 plugin_->LoadOrReloadAccessibility();
858 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
859 plugin_->CreateUrlLoader();
860 plugin_->DocumentLoadComplete();
863 TEST_F(PdfViewWebPluginTest,
864 LoadOrReloadAccessibilityAfterDocumentLoadComplete) {
865 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
867 plugin_->CreateUrlLoader();
868 plugin_->DocumentLoadComplete();
870 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
871 plugin_->LoadOrReloadAccessibility();
874 TEST_F(PdfViewWebPluginTest,
875 LoadOrReloadAccessibilityAfterDocumentLoadCompleteRepeated) {
876 plugin_->CreateUrlLoader();
877 plugin_->DocumentLoadComplete();
878 plugin_->LoadOrReloadAccessibility();
880 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
881 plugin_->LoadOrReloadAccessibility();
884 TEST_F(PdfViewWebPluginTest,
885 LoadOrReloadAccessibilityResetsAccessibilityPageIndex) {
886 plugin_->CreateUrlLoader();
887 plugin_->DocumentLoadComplete();
888 plugin_->LoadOrReloadAccessibility();
889 EXPECT_EQ(plugin_->next_accessibility_page_index_for_testing(), 0);
890 plugin_->set_next_accessibility_page_index_for_testing(5);
892 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
893 plugin_->LoadOrReloadAccessibility();
894 EXPECT_EQ(plugin_->next_accessibility_page_index_for_testing(), 0);
897 TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithNoPermissions) {
898 EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut |
899 kContentRestrictionPaste | kContentRestrictionPrint,
900 plugin_->GetContentRestrictionsForTesting());
901 EXPECT_FALSE(plugin_->CanCopy());
904 TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithCopyAllowed) {
905 EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
906 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
907 .WillRepeatedly(Return(true));
909 EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste |
910 kContentRestrictionPrint,
911 plugin_->GetContentRestrictionsForTesting());
912 EXPECT_TRUE(plugin_->CanCopy());
915 TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithPrintLowQualityAllowed) {
916 EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
917 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
918 .WillRepeatedly(Return(true));
920 EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut |
921 kContentRestrictionPaste,
922 plugin_->GetContentRestrictionsForTesting());
925 TEST_F(PdfViewWebPluginTest,
926 GetContentRestrictionsWithCopyAndPrintLowQualityAllowed) {
927 EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
928 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
929 .WillRepeatedly(Return(true));
930 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
931 .WillRepeatedly(Return(true));
933 EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste,
934 plugin_->GetContentRestrictionsForTesting());
937 TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithPrintAllowed) {
938 EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
939 EXPECT_CALL(*engine_ptr_,
940 HasPermission(DocumentPermission::kPrintHighQuality))
941 .WillRepeatedly(Return(true));
942 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
943 .WillRepeatedly(Return(true));
945 EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut |
946 kContentRestrictionPaste,
947 plugin_->GetContentRestrictionsForTesting());
950 TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithCopyAndPrintAllowed) {
951 EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
952 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
953 .WillRepeatedly(Return(true));
954 EXPECT_CALL(*engine_ptr_,
955 HasPermission(DocumentPermission::kPrintHighQuality))
956 .WillRepeatedly(Return(true));
957 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
958 .WillRepeatedly(Return(true));
960 EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste,
961 plugin_->GetContentRestrictionsForTesting());
964 TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithNoPermissions) {
965 AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfoForTesting();
967 EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
968 EXPECT_FALSE(doc_info.text_accessible);
969 EXPECT_FALSE(doc_info.text_copyable);
972 TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithCopyAllowed) {
973 EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
974 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
975 .WillRepeatedly(Return(true));
977 AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfoForTesting();
979 EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
980 EXPECT_FALSE(doc_info.text_accessible);
981 EXPECT_TRUE(doc_info.text_copyable);
984 TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithCopyAccessibleAllowed) {
985 EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
986 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopyAccessible))
987 .WillRepeatedly(Return(true));
989 AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfoForTesting();
991 EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
992 EXPECT_TRUE(doc_info.text_accessible);
993 EXPECT_FALSE(doc_info.text_copyable);
996 TEST_F(PdfViewWebPluginTest,
997 GetAccessibilityDocInfoWithCopyAndCopyAccessibleAllowed) {
998 EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
999 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
1000 .WillRepeatedly(Return(true));
1001 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopyAccessible))
1002 .WillRepeatedly(Return(true));
1004 AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfoForTesting();
1006 EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
1007 EXPECT_TRUE(doc_info.text_accessible);
1008 EXPECT_TRUE(doc_info.text_copyable);
1011 TEST_F(PdfViewWebPluginTest, UpdateGeometrySetsPluginRect) {
1012 EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f));
1013 TestUpdateGeometrySetsPluginRect(
1014 /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(4, 4, 12, 12),
1015 /*expected_device_scale=*/2.0f,
1016 /*expected_plugin_rect=*/gfx::Rect(4, 4, 12, 12));
1019 TEST_F(PdfViewWebPluginTest,
1020 UpdateGeometrySetsPluginRectOnVariousDeviceScales) {
1021 struct UpdateGeometryParams {
1022 // The plugin container's device scale.
1025 // The window rect in CSS pixels.
1026 gfx::Rect window_rect;
1028 // The expected plugin device scale.
1029 float expected_device_scale;
1031 // The expected plugin rect in device pixels.
1032 gfx::Rect expected_plugin_rect;
1035 static constexpr UpdateGeometryParams kUpdateGeometryParams[] = {
1036 {1.0f, gfx::Rect(3, 4, 5, 6), 1.0f, gfx::Rect(3, 4, 5, 6)},
1037 {2.0f, gfx::Rect(3, 4, 5, 6), 2.0f, gfx::Rect(3, 4, 5, 6)},
1040 for (const auto& params : kUpdateGeometryParams) {
1041 TestUpdateGeometrySetsPluginRect(params.device_scale, params.window_rect,
1042 params.expected_device_scale,
1043 params.expected_plugin_rect);
1047 TEST_F(PdfViewWebPluginTest, UpdateGeometrySetsPluginRectWithEmptyWindow) {
1048 EXPECT_CALL(*engine_ptr_, ZoomUpdated).Times(0);
1049 TestUpdateGeometrySetsPluginRect(
1050 /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(2, 2, 0, 0),
1051 /*expected_device_scale=*/1.0f, /*expected_plugin_rect=*/gfx::Rect());
1054 TEST_F(PdfViewWebPluginTest, UpdateGeometryScroll) {
1055 SetDocumentDimensions({100, 200});
1057 EXPECT_CALL(*client_ptr_, GetScrollPosition)
1058 .WillRepeatedly(Return(gfx::PointF(4.0f, 6.0f)));
1059 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(4));
1060 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(6));
1061 UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
1064 TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollStopped) {
1065 SetDocumentDimensions({100, 200});
1067 plugin_->OnMessage(ParseMessage(R"({
1068 "type": "stopScrolling",
1071 EXPECT_CALL(*client_ptr_, GetScrollPosition)
1072 .WillRepeatedly(Return(gfx::PointF(4.0f, 6.0f)));
1073 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition).Times(0);
1074 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition).Times(0);
1075 UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
1078 TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollUnderflow) {
1079 SetDocumentDimensions({100, 200});
1081 EXPECT_CALL(*client_ptr_, GetScrollPosition)
1082 .WillRepeatedly(Return(gfx::PointF(-1.0f, -1.0f)));
1083 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(0));
1084 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(0));
1085 UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
1088 TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollOverflow) {
1089 SetDocumentDimensions({100, 200});
1091 EXPECT_CALL(*client_ptr_, GetScrollPosition)
1092 .WillRepeatedly(Return(gfx::PointF(96.0f, 195.0f)));
1093 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(95));
1094 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(194));
1095 UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
1098 TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollOverflowZoomed) {
1099 SetDocumentDimensions({100, 200});
1100 SendViewportMessage(/*zoom=*/2.0);
1102 EXPECT_CALL(*client_ptr_, GetScrollPosition)
1103 .WillRepeatedly(Return(gfx::PointF(196.0f, 395.0f)));
1104 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(195));
1105 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(394));
1106 UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
1109 TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollScaled) {
1110 SetDocumentDimensions({100, 200});
1112 EXPECT_CALL(*client_ptr_, GetScrollPosition)
1113 .WillRepeatedly(Return(gfx::PointF(4.0f, 6.0f)));
1114 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(4));
1115 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(6));
1116 UpdatePluginGeometryWithoutWaiting(2.0f, gfx::Rect(3, 4, 5, 6));
1119 TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollOverflowScaled) {
1120 SetDocumentDimensions({100, 200});
1122 EXPECT_CALL(*client_ptr_, GetScrollPosition)
1123 .WillRepeatedly(Return(gfx::PointF(195.0f, 395.0f)));
1124 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(194));
1125 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(394));
1126 UpdatePluginGeometryWithoutWaiting(2.0f, gfx::Rect(3, 4, 5, 6));
1129 TEST_F(PdfViewWebPluginTest, SetCaretPosition) {
1130 SetDocumentDimensions({16, 9});
1131 UpdatePluginGeometryWithoutWaiting(1.0f, {10, 20, 20, 5});
1133 EXPECT_CALL(*engine_ptr_, SetCaretPosition(gfx::Point(2, 3)));
1134 plugin_->SetCaretPosition({4.0f, 3.0f});
1137 TEST_F(PdfViewWebPluginTest, SetCaretPositionNegativeOrigin) {
1138 SetDocumentDimensions({16, 9});
1139 UpdatePluginGeometryWithoutWaiting(1.0f, {-10, -20, 20, 5});
1141 EXPECT_CALL(*engine_ptr_, SetCaretPosition(gfx::Point(2, 3)));
1142 plugin_->SetCaretPosition({4.0f, 3.0f});
1145 TEST_F(PdfViewWebPluginTest, SetCaretPositionFractional) {
1146 SetDocumentDimensions({16, 9});
1147 UpdatePluginGeometryWithoutWaiting(1.0f, {10, 20, 20, 5});
1149 EXPECT_CALL(*engine_ptr_, SetCaretPosition(gfx::Point(1, 2)));
1150 plugin_->SetCaretPosition({3.9f, 2.9f});
1153 TEST_F(PdfViewWebPluginTest, SetCaretPositionScaled) {
1154 SetDocumentDimensions({16, 9});
1155 UpdatePluginGeometryWithoutWaiting(2.0f, {20, 40, 40, 10});
1157 EXPECT_CALL(*engine_ptr_, SetCaretPosition(gfx::Point(4, 6)));
1158 plugin_->SetCaretPosition({4.0f, 3.0f});
1161 TEST_F(PdfViewWebPluginTest, PaintEmptySnapshots) {
1162 TestPaintEmptySnapshots(/*device_scale=*/4.0f,
1163 /*window_rect=*/gfx::Rect(10, 10, 20, 20),
1164 /*paint_rect=*/gfx::Rect(5, 5, 15, 15),
1165 /*expected_clipped_rect=*/gfx::Rect(10, 10, 10, 10));
1168 TEST_F(PdfViewWebPluginTest, PaintSnapshots) {
1169 TestPaintSnapshots(/*device_scale=*/4.0f,
1170 /*window_rect=*/gfx::Rect(10, 10, 20, 20),
1171 /*paint_rect=*/gfx::Rect(5, 5, 15, 15),
1172 /*expected_clipped_rect=*/gfx::Rect(10, 10, 10, 10));
1175 TEST_F(PdfViewWebPluginTest, PaintSnapshotsWithVariousDeviceScales) {
1176 static constexpr PaintParams kPaintWithVariousScalesParams[] = {
1177 {0.4f, gfx::Rect(8, 8, 30, 30), gfx::Rect(10, 10, 30, 30),
1178 gfx::Rect(10, 10, 28, 28)},
1179 {1.0f, gfx::Rect(8, 8, 30, 30), gfx::Rect(10, 10, 30, 30),
1180 gfx::Rect(10, 10, 28, 28)},
1181 {4.0f, gfx::Rect(8, 8, 30, 30), gfx::Rect(10, 10, 30, 30),
1182 gfx::Rect(10, 10, 28, 28)},
1185 for (const auto& params : kPaintWithVariousScalesParams) {
1186 TestPaintSnapshots(params.device_scale, params.window_rect,
1187 params.paint_rect, params.expected_clipped_rect);
1191 TEST_F(PdfViewWebPluginTest, PaintSnapshotsWithVariousRectPositions) {
1192 static constexpr PaintParams kPaintWithVariousPositionsParams[] = {
1193 // The window origin falls outside the `paint_rect` area.
1194 {4.0f, gfx::Rect(10, 10, 20, 20), gfx::Rect(5, 5, 15, 15),
1195 gfx::Rect(10, 10, 10, 10)},
1196 // The window origin falls within the `paint_rect` area.
1197 {4.0f, gfx::Rect(4, 4, 20, 20), gfx::Rect(8, 8, 15, 15),
1198 gfx::Rect(8, 8, 15, 15)},
1201 for (const auto& params : kPaintWithVariousPositionsParams) {
1202 TestPaintSnapshots(params.device_scale, params.window_rect,
1203 params.paint_rect, params.expected_clipped_rect);
1207 TEST_F(PdfViewWebPluginTest, OnPaintWithMultiplePaintRects) {
1208 SetDocumentDimensions({100, 200});
1209 UpdatePluginGeometryWithoutWaiting(/*device_scale=*/1.0f,
1210 gfx::Rect(0, 0, 40, 40));
1212 EXPECT_CALL(*engine_ptr_, Paint)
1214 [](const gfx::Rect& rect, SkBitmap& /*image_data*/,
1215 std::vector<gfx::Rect>& ready,
1216 std::vector<gfx::Rect>& /*pending*/) { ready.push_back(rect); });
1217 std::vector<PaintReadyRect> ready;
1218 std::vector<gfx::Rect> pending;
1220 /*paint_rects=*/{gfx::Rect(5, 5, 10, 10), gfx::Rect(20, 20, 10, 10)},
1223 // Expect three paints: an initial background-clearing paint, and one for each
1224 // requested paint rectangle.
1225 ASSERT_THAT(ready, SizeIs(3));
1226 EXPECT_THAT(pending, IsEmpty());
1228 EXPECT_EQ(gfx::Rect(0, 0, 90, 90), ready[0].rect());
1229 EXPECT_TRUE(ready[0].flush_now());
1231 EXPECT_EQ(gfx::Rect(5, 5, 10, 10), ready[1].rect());
1232 EXPECT_FALSE(ready[1].flush_now());
1234 EXPECT_EQ(gfx::Rect(20, 20, 10, 10), ready[2].rect());
1235 EXPECT_FALSE(ready[2].flush_now());
1237 // All the requested paints should share the same `SkImage`.
1238 EXPECT_NE(&ready[0].image(), &ready[1].image());
1239 EXPECT_EQ(&ready[1].image(), &ready[2].image());
1242 TEST_F(PdfViewWebPluginTest, UpdateLayerTransformWithIdentity) {
1243 plugin_->UpdateLayerTransform(1.0f, gfx::Vector2dF());
1244 TestPaintSnapshots(/*device_scale=*/4.0f,
1245 /*window_rect=*/gfx::Rect(10, 10, 20, 20),
1246 /*paint_rect=*/gfx::Rect(10, 10, 20, 20),
1247 /*expected_clipped_rect=*/gfx::Rect(10, 10, 20, 20));
1250 TEST_F(PdfViewWebPluginTest, UpdateLayerTransformWithScale) {
1251 plugin_->UpdateLayerTransform(0.5f, gfx::Vector2dF());
1252 TestPaintSnapshots(/*device_scale=*/4.0f,
1253 /*window_rect=*/gfx::Rect(10, 10, 20, 20),
1254 /*paint_rect=*/gfx::Rect(10, 10, 20, 20),
1255 /*expected_clipped_rect=*/gfx::Rect(10, 10, 10, 10));
1258 TEST_F(PdfViewWebPluginTest, UpdateLayerTransformWithTranslate) {
1259 plugin_->UpdateLayerTransform(1.0f, gfx::Vector2dF(-1.25, 1.25));
1260 TestPaintSnapshots(/*device_scale=*/4.0f,
1261 /*window_rect=*/gfx::Rect(10, 10, 20, 20),
1262 /*paint_rect=*/gfx::Rect(10, 10, 20, 20),
1263 /*expected_clipped_rect=*/gfx::Rect(10, 15, 15, 15));
1266 TEST_F(PdfViewWebPluginTest, UpdateLayerTransformWithScaleAndTranslate) {
1267 plugin_->UpdateLayerTransform(0.5f, gfx::Vector2dF(-1.25, 1.25));
1268 TestPaintSnapshots(/*device_scale=*/4.0f,
1269 /*window_rect=*/gfx::Rect(10, 10, 20, 20),
1270 /*paint_rect=*/gfx::Rect(10, 10, 20, 20),
1271 /*expected_clipped_rect=*/gfx::Rect(10, 15, 5, 10));
1274 TEST_F(PdfViewWebPluginTest, HandleViewportMessageBeforeDocumentLoadComplete) {
1275 EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout(DocumentLayout::Options()));
1276 EXPECT_CALL(*client_ptr_, PostMessage).Times(0);
1278 plugin_->OnMessage(ParseMessage(R"({
1280 "userInitiated": false,
1284 "defaultPageOrientation": 0,
1285 "twoUpViewEnabled": false,
1293 TEST_F(PdfViewWebPluginTest, HandleViewportMessageAfterDocumentLoadComplete) {
1294 plugin_->DocumentLoadComplete();
1296 EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout(DocumentLayout::Options()));
1297 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
1298 "type": "loadProgress",
1302 plugin_->OnMessage(ParseMessage(R"({
1304 "userInitiated": false,
1308 "defaultPageOrientation": 0,
1309 "twoUpViewEnabled": false,
1317 TEST_F(PdfViewWebPluginTest, HandleViewportMessageSubsequently) {
1318 plugin_->OnMessage(ParseMessage(R"({
1320 "userInitiated": false,
1324 "defaultPageOrientation": 0,
1325 "twoUpViewEnabled": false,
1332 DocumentLayout::Options two_up_options;
1333 two_up_options.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
1334 EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout(two_up_options));
1335 EXPECT_CALL(*client_ptr_, PostMessage).Times(0);
1337 plugin_->OnMessage(ParseMessage(R"({
1339 "userInitiated": false,
1343 "defaultPageOrientation": 0,
1344 "twoUpViewEnabled": true,
1352 TEST_F(PdfViewWebPluginTest, HandleViewportMessageScroll) {
1353 EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout)
1354 .WillRepeatedly(Return(gfx::Size(16, 9)));
1355 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(2));
1356 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(3));
1358 plugin_->OnMessage(ParseMessage(R"({
1360 "userInitiated": false,
1364 "defaultPageOrientation": 0,
1365 "twoUpViewEnabled": false,
1373 TEST_F(PdfViewWebPluginTest, HandleViewportMessageScrollRightToLeft) {
1374 EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout)
1375 .WillRepeatedly(Return(gfx::Size(16, 9)));
1376 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(2));
1377 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(3));
1379 plugin_->OnMessage(ParseMessage(R"({
1381 "userInitiated": false,
1385 "defaultPageOrientation": 0,
1386 "twoUpViewEnabled": false,
1394 TEST_F(PdfViewWebPluginTest, HandleSetBackgroundColorMessage) {
1395 ASSERT_NE(SK_ColorGREEN, plugin_->GetBackgroundColor());
1397 base::Value::Dict message;
1398 message.Set("type", "setBackgroundColor");
1399 message.Set("color", static_cast<double>(SK_ColorGREEN));
1400 plugin_->OnMessage(message);
1402 EXPECT_EQ(SK_ColorGREEN, plugin_->GetBackgroundColor());
1405 TEST_F(PdfViewWebPluginTest, HandleInputEvent) {
1406 UpdatePluginGeometryWithoutWaiting(2.0f, {0, 0, 20, 20});
1408 EXPECT_CALL(*engine_ptr_, HandleInputEvent)
1409 .WillRepeatedly([](const blink::WebInputEvent& event) {
1410 if (!blink::WebInputEvent::IsMouseEventType(event.GetType())) {
1411 ADD_FAILURE() << "Unexpected event type: " << event.GetType();
1415 const auto& mouse_event =
1416 static_cast<const blink::WebMouseEvent&>(event);
1417 EXPECT_EQ(blink::WebInputEvent::Type::kMouseDown,
1418 mouse_event.GetType());
1419 EXPECT_EQ(gfx::PointF(10.0f, 40.0f), mouse_event.PositionInWidget());
1423 blink::WebMouseEvent mouse_event;
1424 mouse_event.SetType(blink::WebInputEvent::Type::kMouseDown);
1425 mouse_event.SetPositionInWidget(10.0f, 20.0f);
1427 ui::Cursor dummy_cursor;
1428 EXPECT_EQ(blink::WebInputEventResult::kHandledApplication,
1429 plugin_->HandleInputEvent(
1430 blink::WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()),
1434 class PdfViewWebPluginImeTest : public PdfViewWebPluginTest {
1436 void TestImeSetCompositionForPlugin(const blink::WebString& text) {
1437 EXPECT_CALL(*engine_ptr_, HandleInputEvent).Times(0);
1438 plugin_->ImeSetCompositionForPlugin(text, std::vector<ui::ImeTextSpan>(),
1440 /*selection_start=*/0,
1441 /*selection_end=*/0);
1444 void TestImeFinishComposingTextForPlugin(
1445 const blink::WebString& expected_text) {
1446 InSequence sequence;
1447 std::u16string expected_text16 = expected_text.Utf16();
1448 if (expected_text16.size()) {
1449 for (const auto& c : expected_text16) {
1450 base::StringPiece16 expected_key(&c, 1);
1451 EXPECT_CALL(*engine_ptr_,
1452 HandleInputEvent(IsExpectedImeKeyEvent(expected_key)))
1453 .WillOnce(Return(true));
1456 EXPECT_CALL(*engine_ptr_, HandleInputEvent).Times(0);
1458 plugin_->ImeFinishComposingTextForPlugin(false);
1461 void TestImeCommitTextForPlugin(const blink::WebString& text) {
1462 InSequence sequence;
1463 std::u16string expected_text16 = text.Utf16();
1464 if (expected_text16.size()) {
1465 for (const auto& c : expected_text16) {
1466 base::StringPiece16 event(&c, 1);
1467 EXPECT_CALL(*engine_ptr_,
1468 HandleInputEvent(IsExpectedImeKeyEvent(event)))
1469 .WillOnce(Return(true));
1472 EXPECT_CALL(*engine_ptr_, HandleInputEvent).Times(0);
1474 plugin_->ImeCommitTextForPlugin(text, std::vector<ui::ImeTextSpan>(),
1476 /*relative_cursor_pos=*/0);
1480 TEST_F(PdfViewWebPluginImeTest, ImeSetCompositionAndFinishAscii) {
1481 const blink::WebString text = blink::WebString::FromASCII("input");
1482 TestImeSetCompositionForPlugin(text);
1483 TestImeFinishComposingTextForPlugin(text);
1486 TEST_F(PdfViewWebPluginImeTest, ImeSetCompositionAndFinishUnicode) {
1487 const blink::WebString text = blink::WebString::FromUTF16(u"你好");
1488 TestImeSetCompositionForPlugin(text);
1489 TestImeFinishComposingTextForPlugin(text);
1490 // Calling ImeFinishComposingTextForPlugin() again is a no-op.
1491 TestImeFinishComposingTextForPlugin("");
1494 TEST_F(PdfViewWebPluginImeTest, ImeSetCompositionAndFinishEmpty) {
1495 const blink::WebString text;
1496 TestImeSetCompositionForPlugin(text);
1497 TestImeFinishComposingTextForPlugin(text);
1500 TEST_F(PdfViewWebPluginImeTest, ImeCommitTextForPluginAscii) {
1501 const blink::WebString text = blink::WebString::FromASCII("a b");
1502 TestImeCommitTextForPlugin(text);
1505 TEST_F(PdfViewWebPluginImeTest, ImeCommitTextForPluginUnicode) {
1506 const blink::WebString text = blink::WebString::FromUTF16(u"さようなら");
1507 TestImeCommitTextForPlugin(text);
1510 TEST_F(PdfViewWebPluginImeTest, ImeCommitTextForPluginEmpty) {
1511 const blink::WebString text;
1512 TestImeCommitTextForPlugin(text);
1515 TEST_F(PdfViewWebPluginTest, SelectionChanged) {
1516 plugin_->EnableAccessibility();
1517 plugin_->DocumentLoadComplete();
1518 UpdatePluginGeometryWithoutWaiting(1.0f, {300, 56, 20, 5});
1519 SetDocumentDimensions({16, 9});
1521 AccessibilityViewportInfo viewport_info;
1522 EXPECT_CALL(pdf_service_, SelectionChanged(gfx::PointF(-8.0f, -20.0f), 40,
1523 gfx::PointF(52.0f, 60.0f), 80));
1524 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityViewportInfo)
1525 .WillOnce(SaveArg<0>(&viewport_info));
1526 plugin_->SelectionChanged({-10, -20, 30, 40}, {50, 60, 70, 80});
1528 EXPECT_EQ(gfx::Point(), viewport_info.scroll);
1529 pdf_receiver_.FlushForTesting();
1532 TEST_F(PdfViewWebPluginTest, SelectionChangedNegativeOrigin) {
1533 plugin_->EnableAccessibility();
1534 plugin_->DocumentLoadComplete();
1535 UpdatePluginGeometryWithoutWaiting(1.0f, {-300, -56, 20, 5});
1536 SetDocumentDimensions({16, 9});
1538 AccessibilityViewportInfo viewport_info;
1539 EXPECT_CALL(pdf_service_, SelectionChanged(gfx::PointF(-8.0f, -20.0f), 40,
1540 gfx::PointF(52.0f, 60.0f), 80));
1541 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityViewportInfo)
1542 .WillOnce(SaveArg<0>(&viewport_info));
1543 plugin_->SelectionChanged({-10, -20, 30, 40}, {50, 60, 70, 80});
1545 EXPECT_EQ(gfx::Point(), viewport_info.scroll);
1546 pdf_receiver_.FlushForTesting();
1549 TEST_F(PdfViewWebPluginTest, SelectionChangedScaled) {
1550 plugin_->EnableAccessibility();
1551 plugin_->DocumentLoadComplete();
1552 UpdatePluginGeometryWithoutWaiting(2.0f, {600, 112, 40, 10});
1553 SetDocumentDimensions({16, 9});
1555 AccessibilityViewportInfo viewport_info;
1556 EXPECT_CALL(pdf_service_, SelectionChanged(gfx::PointF(-8.0f, -20.0f), 40,
1557 gfx::PointF(52.0f, 60.0f), 80));
1558 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityViewportInfo)
1559 .WillOnce(SaveArg<0>(&viewport_info));
1560 plugin_->SelectionChanged({-20, -40, 60, 80}, {100, 120, 140, 160});
1562 EXPECT_EQ(gfx::Point(), viewport_info.scroll);
1563 pdf_receiver_.FlushForTesting();
1566 TEST_F(PdfViewWebPluginTest, ChangeTextSelection) {
1567 ASSERT_FALSE(plugin_->HasSelection());
1568 ASSERT_TRUE(plugin_->SelectionAsText().IsEmpty());
1569 ASSERT_TRUE(plugin_->SelectionAsMarkup().IsEmpty());
1571 static constexpr char kSelectedText[] = "1234";
1572 EXPECT_CALL(*client_ptr_,
1573 TextSelectionChanged(blink::WebString::FromUTF8(kSelectedText), 0,
1576 plugin_->SetSelectedText(kSelectedText);
1577 EXPECT_TRUE(plugin_->HasSelection());
1578 EXPECT_EQ(kSelectedText, plugin_->SelectionAsText().Utf8());
1579 EXPECT_EQ(kSelectedText, plugin_->SelectionAsMarkup().Utf8());
1581 static constexpr char kEmptyText[] = "";
1582 EXPECT_CALL(*client_ptr_,
1583 TextSelectionChanged(blink::WebString::FromUTF8(kEmptyText), 0,
1585 plugin_->SetSelectedText(kEmptyText);
1586 EXPECT_FALSE(plugin_->HasSelection());
1587 EXPECT_TRUE(plugin_->SelectionAsText().IsEmpty());
1588 EXPECT_TRUE(plugin_->SelectionAsMarkup().IsEmpty());
1591 TEST_F(PdfViewWebPluginTest, SelectAll) {
1592 EXPECT_CALL(*engine_ptr_, SelectAll);
1594 EXPECT_TRUE(plugin_->ExecuteEditCommand(
1595 /*name=*/blink::WebString::FromASCII("SelectAll"),
1596 /*value=*/blink::WebString()));
1599 TEST_F(PdfViewWebPluginTest, FormTextFieldFocusChangeUpdatesTextInputType) {
1600 ASSERT_EQ(blink::WebTextInputType::kWebTextInputTypeNone,
1601 plugin_->GetPluginTextInputType());
1603 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeText);
1604 plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kText);
1606 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
1607 plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kNoFocus);
1609 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeText);
1610 plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kText);
1612 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
1613 plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kNonText);
1616 TEST_F(PdfViewWebPluginTest, SearchString) {
1617 static constexpr char16_t kPattern[] = u"fox";
1618 static constexpr char16_t kTarget[] =
1619 u"The quick brown fox jumped over the lazy Fox";
1622 static constexpr PDFEngine::Client::SearchStringResult kExpectation[] = {
1625 plugin_->SearchString(kTarget, kPattern, /*case_sensitive=*/true),
1626 Pointwise(SearchStringResultEq(), kExpectation));
1629 static constexpr PDFEngine::Client::SearchStringResult kExpectation[] = {
1632 plugin_->SearchString(kTarget, kPattern, /*case_sensitive=*/false),
1633 Pointwise(SearchStringResultEq(), kExpectation));
1637 TEST_F(PdfViewWebPluginTest, UpdateFocus) {
1638 MockFunction<void(int checkpoint_num)> checkpoint;
1641 InSequence sequence;
1643 // Focus false -> true: Triggers updates.
1644 EXPECT_CALL(*client_ptr_, UpdateTextInputState);
1645 EXPECT_CALL(*client_ptr_, UpdateSelectionBounds);
1646 EXPECT_CALL(checkpoint, Call(1));
1648 // Focus true -> true: No updates.
1649 EXPECT_CALL(checkpoint, Call(2));
1651 // Focus true -> false: Triggers updates. `UpdateTextInputState` is called
1652 // twice because it also gets called due to
1653 // `PDFiumEngine::UpdateFocus(false)`.
1654 EXPECT_CALL(*client_ptr_, UpdateTextInputState).Times(2);
1655 EXPECT_CALL(*client_ptr_, UpdateSelectionBounds);
1656 EXPECT_CALL(checkpoint, Call(3));
1658 // Focus false -> false: No updates.
1659 EXPECT_CALL(checkpoint, Call(4));
1661 // Focus false -> true: Triggers updates.
1662 EXPECT_CALL(*client_ptr_, UpdateTextInputState);
1663 EXPECT_CALL(*client_ptr_, UpdateSelectionBounds);
1666 // The focus type does not matter in this test.
1667 plugin_->UpdateFocus(/*focused=*/true, blink::mojom::FocusType::kNone);
1669 plugin_->UpdateFocus(/*focused=*/true, blink::mojom::FocusType::kNone);
1671 plugin_->UpdateFocus(/*focused=*/false, blink::mojom::FocusType::kNone);
1673 plugin_->UpdateFocus(/*focused=*/false, blink::mojom::FocusType::kNone);
1675 plugin_->UpdateFocus(/*focused=*/true, blink::mojom::FocusType::kNone);
1678 TEST_F(PdfViewWebPluginTest, ShouldDispatchImeEventsToPlugin) {
1679 ASSERT_TRUE(plugin_->ShouldDispatchImeEventsToPlugin());
1682 TEST_F(PdfViewWebPluginTest, CaretChange) {
1683 EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f));
1684 UpdatePluginGeometry(
1685 /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(12, 24, 36, 48));
1686 plugin_->CaretChanged(gfx::Rect(10, 20, 30, 40));
1687 EXPECT_EQ(gfx::Rect(28, 20, 30, 40), plugin_->GetPluginCaretBounds());
1690 TEST_F(PdfViewWebPluginTest, EnteredEditMode) {
1691 EXPECT_CALL(pdf_service_, SetPluginCanSave(true));
1692 EXPECT_CALL(*client_ptr_, PostMessage).Times(AnyNumber());
1693 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
1694 "type": "setIsEditing",
1696 plugin_->EnteredEditMode();
1698 pdf_receiver_.FlushForTesting();
1701 TEST_F(PdfViewWebPluginTest, NotifyNumberOfFindResultsChanged) {
1702 plugin_->StartFind("x", /*case_sensitive=*/false, /*identifier=*/123);
1704 const std::vector<gfx::Rect> tickmarks = {gfx::Rect(1, 2), gfx::Rect(3, 4)};
1705 plugin_->UpdateTickMarks(tickmarks);
1707 EXPECT_CALL(*client_ptr_, ReportFindInPageTickmarks(tickmarks));
1708 EXPECT_CALL(*client_ptr_, ReportFindInPageMatchCount(123, 5, true));
1709 plugin_->NotifyNumberOfFindResultsChanged(/*total=*/5, /*final_result=*/true);
1712 TEST_F(PdfViewWebPluginTest, OnDocumentLoadComplete) {
1713 base::Value::Dict metadata;
1714 metadata.Set("fileSize", "0 B");
1715 metadata.Set("linearized", false);
1716 metadata.Set("pageSize", "Varies");
1717 metadata.Set("canSerializeDocument", true);
1719 base::Value::Dict message;
1720 message.Set("type", "metadata");
1721 message.Set("metadataData", std::move(metadata));
1723 EXPECT_CALL(*client_ptr_, PostMessage);
1724 EXPECT_CALL(*client_ptr_, PostMessage(Eq(std::ref(message))));
1725 plugin_->DocumentLoadComplete();
1728 class PdfViewWebPluginWithDocInfoTest : public PdfViewWebPluginTest {
1730 void SetUp() override {
1731 PdfViewWebPluginTest::SetUp();
1732 if (IsPortfolioEnabled()) {
1733 scoped_feature_list_.InitAndEnableFeature(features::kPdfPortfolio);
1737 bool IsPortfolioEnabled() { return GetParam(); }
1740 class TestPDFiumEngineWithDocInfo : public TestPDFiumEngine {
1742 explicit TestPDFiumEngineWithDocInfo(PDFEngine::Client* client)
1743 : TestPDFiumEngine(client) {
1744 InitializeDocumentAttachments();
1745 InitializeDocumentMetadata();
1748 base::Value::List GetBookmarks() override {
1749 // Create `bookmark1` which navigates to an in-doc position. This bookmark
1750 // will be in the top-level bookmark list.
1751 base::Value::Dict bookmark1;
1752 bookmark1.Set("title", "Bookmark 1");
1753 bookmark1.Set("page", 2);
1754 bookmark1.Set("x", 10);
1755 bookmark1.Set("y", 20);
1756 bookmark1.Set("zoom", 2.0);
1758 // Create `bookmark2` which navigates to a web page. This bookmark will be
1759 // a child of `bookmark1`.
1760 base::Value::Dict bookmark2;
1761 bookmark2.Set("title", "Bookmark 2");
1762 bookmark2.Set("uri", "test.com");
1764 base::Value::List children_of_bookmark1;
1765 children_of_bookmark1.Append(std::move(bookmark2));
1766 bookmark1.Set("children", std::move(children_of_bookmark1));
1768 // Create the top-level bookmark list.
1769 base::Value::List bookmarks;
1770 bookmarks.Append(std::move(bookmark1));
1774 absl::optional<gfx::Size> GetUniformPageSizePoints() override {
1775 return gfx::Size(1000, 1200);
1779 void InitializeDocumentAttachments() {
1780 doc_attachment_info_list().resize(3);
1782 // A regular attachment.
1783 doc_attachment_info_list()[0].name = u"attachment1.txt";
1784 doc_attachment_info_list()[0].creation_date = u"D:20170712214438-07'00'";
1785 doc_attachment_info_list()[0].modified_date = u"D:20160115091400";
1786 doc_attachment_info_list()[0].is_readable = true;
1787 doc_attachment_info_list()[0].size_bytes = 13u;
1789 // An unreadable attachment.
1790 doc_attachment_info_list()[1].name = u"attachment2.pdf";
1791 doc_attachment_info_list()[1].is_readable = false;
1793 // A readable attachment that exceeds download size limit.
1794 doc_attachment_info_list()[2].name = u"attachment3.mov";
1795 doc_attachment_info_list()[2].is_readable = true;
1796 doc_attachment_info_list()[2].size_bytes =
1797 PdfViewWebPlugin::kMaximumSavedFileSize + 1;
1800 void InitializeDocumentMetadata() {
1801 metadata().version = PdfVersion::k1_7;
1802 metadata().size_bytes = 13u;
1803 metadata().page_count = 13u;
1804 metadata().linearized = true;
1805 metadata().has_attachments = true;
1806 metadata().form_type = FormType::kAcroForm;
1807 metadata().title = "Title";
1808 metadata().author = "Author";
1809 metadata().subject = "Subject";
1810 metadata().keywords = "Keywords";
1811 metadata().creator = "Creator";
1812 metadata().producer = "Producer";
1813 ASSERT_TRUE(base::Time::FromUTCString("2021-05-04 11:12:13",
1814 &metadata().creation_date));
1815 ASSERT_TRUE(base::Time::FromUTCString("2021-06-04 15:16:17",
1816 &metadata().mod_date));
1820 static base::Value::Dict CreateExpectedAttachmentsResponse() {
1821 base::Value::List attachments;
1823 base::Value::Dict attachment;
1824 attachment.Set("name", "attachment1.txt");
1825 attachment.Set("size", 13);
1826 attachment.Set("readable", true);
1827 attachments.Append(std::move(attachment));
1830 base::Value::Dict attachment;
1831 attachment.Set("name", "attachment2.pdf");
1832 attachment.Set("size", 0);
1833 attachment.Set("readable", false);
1834 attachments.Append(std::move(attachment));
1837 base::Value::Dict attachment;
1838 attachment.Set("name", "attachment3.mov");
1839 attachment.Set("size", -1);
1840 attachment.Set("readable", true);
1841 attachments.Append(std::move(attachment));
1844 base::Value::Dict message;
1845 message.Set("type", "attachments");
1846 message.Set("attachmentsData", std::move(attachments));
1850 static base::Value::Dict CreateExpectedBookmarksResponse(
1851 base::Value::List bookmarks) {
1852 base::Value::Dict message;
1853 message.Set("type", "bookmarks");
1854 message.Set("bookmarksData", std::move(bookmarks));
1858 static base::Value::Dict CreateExpectedMetadataResponse() {
1859 base::Value::Dict metadata;
1860 metadata.Set("version", "1.7");
1861 metadata.Set("fileSize", "13 B");
1862 metadata.Set("linearized", true);
1864 metadata.Set("title", "Title");
1865 metadata.Set("author", "Author");
1866 metadata.Set("subject", "Subject");
1867 metadata.Set("keywords", "Keywords");
1868 metadata.Set("creator", "Creator");
1869 metadata.Set("producer", "Producer");
1870 metadata.Set("creationDate",
1871 "5/4/21, 4:12:13\xE2\x80\xAF"
1873 metadata.Set("modDate",
1874 "6/4/21, 8:16:17\xE2\x80\xAF"
1876 metadata.Set("pageSize", "13.89 × 16.67 in (portrait)");
1877 metadata.Set("canSerializeDocument", true);
1879 base::Value::Dict message;
1880 message.Set("type", "metadata");
1881 message.Set("metadataData", std::move(metadata));
1885 void SetUpClient() override {
1886 EXPECT_CALL(*client_ptr_, CreateEngine).WillOnce([this]() {
1887 auto engine = std::make_unique<NiceMock<TestPDFiumEngineWithDocInfo>>(
1889 engine_ptr_ = engine.get();
1894 base::test::ScopedFeatureList scoped_feature_list_;
1897 TEST_P(PdfViewWebPluginWithDocInfoTest, OnDocumentLoadComplete) {
1898 const base::Value::Dict expect_attachments =
1899 CreateExpectedAttachmentsResponse();
1900 const base::Value::Dict expect_bookmarks =
1901 CreateExpectedBookmarksResponse(engine_ptr_->GetBookmarks());
1902 const base::Value::Dict expect_metadata = CreateExpectedMetadataResponse();
1903 EXPECT_CALL(*client_ptr_, PostMessage);
1904 EXPECT_CALL(*client_ptr_, PostMessage(Eq(std::ref(expect_attachments))))
1905 .Times(IsPortfolioEnabled() ? 1 : 0);
1906 EXPECT_CALL(*client_ptr_, PostMessage(Eq(std::ref(expect_bookmarks))));
1907 EXPECT_CALL(*client_ptr_, PostMessage(Eq(std::ref(expect_metadata))));
1908 plugin_->DocumentLoadComplete();
1911 INSTANTIATE_TEST_SUITE_P(All, PdfViewWebPluginWithDocInfoTest, testing::Bool());
1913 class PdfViewWebPluginSaveTest : public PdfViewWebPluginTest {
1915 static void AddDataToValue(base::span<const uint8_t> data,
1916 base::Value& value) {
1917 value.GetDict().Set("dataToSave", base::Value(data));
1920 void SetUpClient() override {
1921 // Ignore non-"saveData" `PdfViewWebPlugin::Client::PostMessage()` calls.
1922 EXPECT_CALL(*client_ptr_, PostMessage)
1923 .WillRepeatedly([](const base::Value::Dict& message) {
1924 EXPECT_NE("saveData", *message.FindString("type"));
1929 #if BUILDFLAG(ENABLE_INK)
1930 TEST_F(PdfViewWebPluginSaveTest, AnnotationInNonEditMode) {
1931 base::Value expected_response = base::test::ParseJson(R"({
1933 "token": "annotation-in-non-edit-mode",
1934 "fileName": "example.pdf",
1935 "editModeForTesting": false,
1937 AddDataToValue(base::make_span(TestPDFiumEngine::kLoadedData),
1940 EXPECT_CALL(pdf_service_, SetPluginCanSave(true));
1941 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
1942 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(expected_response)));
1944 plugin_->OnMessage(ParseMessage(R"({
1946 "saveRequestType": 0,
1947 "token": "annotation-in-non-edit-mode",
1950 pdf_receiver_.FlushForTesting();
1953 TEST_F(PdfViewWebPluginSaveTest, AnnotationInEditMode) {
1954 plugin_->EnteredEditMode();
1955 pdf_receiver_.FlushForTesting();
1957 base::Value expected_response = base::test::ParseJson(R"({
1959 "token": "annotation-in-edit-mode",
1960 "fileName": "example.pdf",
1961 "editModeForTesting": true,
1963 AddDataToValue(base::make_span(TestPDFiumEngine::kSaveData),
1966 EXPECT_CALL(pdf_service_, SetPluginCanSave(true));
1967 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
1968 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(expected_response)));
1970 plugin_->OnMessage(ParseMessage(R"({
1972 "saveRequestType": 0,
1973 "token": "annotation-in-edit-mode",
1976 pdf_receiver_.FlushForTesting();
1978 #endif // BUILDFLAG(ENABLE_INK)
1980 TEST_F(PdfViewWebPluginSaveTest, OriginalInNonEditMode) {
1982 InSequence pdf_service_sequence;
1984 EXPECT_CALL(pdf_service_, SetPluginCanSave(false));
1987 SaveUrlAs(GURL(kPdfUrl), network::mojom::ReferrerPolicy::kDefault));
1988 EXPECT_CALL(pdf_service_, SetPluginCanSave(false));
1991 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
1992 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
1993 "type": "consumeSaveToken",
1994 "token": "original-in-non-edit-mode",
1997 plugin_->OnMessage(ParseMessage(R"({
1999 "saveRequestType": 1,
2000 "token": "original-in-non-edit-mode",
2003 pdf_receiver_.FlushForTesting();
2006 TEST_F(PdfViewWebPluginSaveTest, OriginalInEditMode) {
2007 plugin_->EnteredEditMode();
2008 pdf_receiver_.FlushForTesting();
2011 InSequence pdf_service_sequence;
2013 EXPECT_CALL(pdf_service_, SetPluginCanSave(false));
2016 SaveUrlAs(GURL(kPdfUrl), network::mojom::ReferrerPolicy::kDefault));
2017 EXPECT_CALL(pdf_service_, SetPluginCanSave(true));
2020 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
2021 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
2022 "type": "consumeSaveToken",
2023 "token": "original-in-edit-mode",
2026 plugin_->OnMessage(ParseMessage(R"({
2028 "saveRequestType": 1,
2029 "token": "original-in-edit-mode",
2032 pdf_receiver_.FlushForTesting();
2035 #if BUILDFLAG(ENABLE_INK)
2036 TEST_F(PdfViewWebPluginSaveTest, EditedInNonEditMode) {
2037 base::Value expected_response = base::test::ParseJson(R"({
2039 "token": "edited-in-non-edit-mode",
2040 "fileName": "example.pdf",
2041 "editModeForTesting": false,
2043 AddDataToValue(base::make_span(TestPDFiumEngine::kLoadedData),
2046 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
2047 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(expected_response)));
2049 plugin_->OnMessage(ParseMessage(R"({
2051 "saveRequestType": 2,
2052 "token": "edited-in-non-edit-mode",
2055 #endif // BUILDFLAG(ENABLE_INK)
2057 TEST_F(PdfViewWebPluginSaveTest, EditedInEditMode) {
2058 plugin_->EnteredEditMode();
2060 base::Value expected_response = base::test::ParseJson(R"({
2062 "token": "edited-in-edit-mode",
2063 "fileName": "example.pdf",
2064 "editModeForTesting": true,
2066 AddDataToValue(base::make_span(TestPDFiumEngine::kSaveData),
2069 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
2070 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(expected_response)));
2072 plugin_->OnMessage(ParseMessage(R"({
2074 "saveRequestType": 2,
2075 "token": "edited-in-edit-mode",
2079 class PdfViewWebPluginSubmitFormTest
2080 : public PdfViewWebPluginWithoutInitializeTest {
2082 void SubmitForm(const std::string& url,
2083 base::StringPiece form_data = "data") {
2084 EXPECT_TRUE(plugin_->InitializeForTesting());
2086 EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader).WillOnce([this]() {
2087 auto associated_loader =
2088 std::make_unique<NiceMock<MockWebAssociatedURLLoader>>();
2089 EXPECT_CALL(*associated_loader, LoadAsynchronously)
2090 .WillOnce([this](const blink::WebURLRequest& request,
2091 blink::WebAssociatedURLLoaderClient* /*client*/) {
2092 // TODO(crbug.com/1322928): The `UrlLoader` created by `LoadUrl()`
2093 // and `SubmitForm()` shouldn't use different ownership semantics.
2094 // The loader created by `SubmitForm()` is owned by the plugin, and
2095 // cannot leak past the destruction of the plugin.
2096 request_.CopyFrom(request);
2098 return associated_loader;
2101 plugin_->SubmitForm(url, form_data.data(), form_data.size());
2104 void SubmitFailingForm(const std::string& url) {
2105 EXPECT_TRUE(plugin_->InitializeForTesting());
2107 EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader).Times(0);
2109 constexpr base::StringPiece kFormData = "form data";
2110 plugin_->SubmitForm(url, kFormData.data(), kFormData.size());
2113 blink::WebURLRequest request_;
2116 TEST_F(PdfViewWebPluginSubmitFormTest, RequestMethod) {
2117 SetUpPluginWithUrl("https://www.example.com/path/to/the.pdf");
2119 SubmitForm(/*url=*/"");
2121 EXPECT_EQ(request_.HttpMethod().Utf8(), "POST");
2124 TEST_F(PdfViewWebPluginSubmitFormTest, RequestBody) {
2125 SetUpPluginWithUrl("https://www.example.com/path/to/the.pdf");
2127 constexpr base::StringPiece kFormData = "form data";
2128 SubmitForm(/*url=*/"", kFormData);
2130 blink::WebHTTPBody::Element element;
2131 EXPECT_EQ(request_.HttpBody().ElementCount(), 1u);
2132 ASSERT_TRUE(request_.HttpBody().ElementAt(0, element));
2133 ASSERT_EQ(element.type, blink::HTTPBodyElementType::kTypeData);
2134 EXPECT_THAT(element.data.Copy(), testing::ElementsAreArray(kFormData));
2137 TEST_F(PdfViewWebPluginSubmitFormTest, RelativeUrl) {
2138 SetUpPluginWithUrl("https://www.example.com/path/to/the.pdf");
2140 SubmitForm("relative_endpoint");
2142 EXPECT_EQ(request_.Url().GetString().Utf8(),
2143 "https://www.example.com/path/to/relative_endpoint");
2146 TEST_F(PdfViewWebPluginSubmitFormTest, NoRelativeUrl) {
2147 SetUpPluginWithUrl("https://www.example.com/path/to/the.pdf");
2151 EXPECT_EQ(request_.Url().GetString().Utf8(),
2152 "https://www.example.com/path/to/the.pdf");
2155 TEST_F(PdfViewWebPluginSubmitFormTest, AbsoluteUrl) {
2156 SetUpPluginWithUrl("https://a.example.com/path/to/the.pdf");
2158 SubmitForm("https://b.example.com/relative_endpoint");
2160 EXPECT_EQ(request_.Url().GetString().Utf8(),
2161 "https://b.example.com/relative_endpoint");
2164 TEST_F(PdfViewWebPluginSubmitFormTest, RelativeUrlInvalidDocumentUrl) {
2165 SetUpPluginWithUrl("https://www.%B%Ad.com/path/to/the.pdf");
2167 SubmitFailingForm("relative_endpoint");
2170 TEST_F(PdfViewWebPluginSubmitFormTest, AbsoluteUrlInvalidDocumentUrl) {
2171 SetUpPluginWithUrl("https://www.%B%Ad.com/path/to/the.pdf");
2173 SubmitFailingForm("https://wwww.example.com");
2176 class PdfViewWebPluginPrintTest : public PdfViewWebPluginTest {
2178 void SetUp() override {
2179 PdfViewWebPluginTest::SetUp();
2181 // Size must be at least 1 for conversion to `SkMemoryStream`.
2182 ON_CALL(*engine_ptr_, PrintPages)
2183 .WillByDefault(Return(std::vector<uint8_t>(1)));
2185 canvas_.sk_canvas()->SetPrintingMetafile(&metafile_);
2188 printing::MetafileSkia metafile_;
2191 TEST_F(PdfViewWebPluginPrintTest, HighQuality) {
2192 EXPECT_CALL(*engine_ptr_,
2193 HasPermission(DocumentPermission::kPrintHighQuality))
2194 .WillRepeatedly(Return(true));
2195 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
2196 .WillRepeatedly(Return(true));
2197 ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
2198 plugin_->PrintBegin(blink::WebPrintParams()));
2202 PrintPages(ElementsAre(0),
2203 Field(&blink::WebPrintParams::rasterize_pdf, IsFalse())));
2204 plugin_->PrintPage(0, canvas_.sk_canvas());
2205 plugin_->PrintEnd();
2208 TEST_F(PdfViewWebPluginPrintTest, HighQualityRasterized) {
2209 EXPECT_CALL(*engine_ptr_,
2210 HasPermission(DocumentPermission::kPrintHighQuality))
2211 .WillRepeatedly(Return(true));
2212 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
2213 .WillRepeatedly(Return(true));
2215 blink::WebPrintParams params;
2216 params.rasterize_pdf = true;
2217 ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
2218 plugin_->PrintBegin(params));
2222 PrintPages(ElementsAre(0),
2223 Field(&blink::WebPrintParams::rasterize_pdf, IsTrue())));
2224 plugin_->PrintPage(0, canvas_.sk_canvas());
2225 plugin_->PrintEnd();
2228 // Regression test for crbug.com/1307219.
2229 TEST_F(PdfViewWebPluginPrintTest, LowQuality) {
2230 EXPECT_CALL(*engine_ptr_,
2231 HasPermission(DocumentPermission::kPrintHighQuality))
2232 .WillRepeatedly(Return(false));
2233 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
2234 .WillRepeatedly(Return(true));
2235 ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
2236 plugin_->PrintBegin(blink::WebPrintParams()));
2240 PrintPages(ElementsAre(0),
2241 Field(&blink::WebPrintParams::rasterize_pdf, IsTrue())));
2242 plugin_->PrintPage(0, canvas_.sk_canvas());
2243 plugin_->PrintEnd();
2246 // Regression test for crbug.com/1307219.
2247 TEST_F(PdfViewWebPluginPrintTest, LowQualityRasterized) {
2248 EXPECT_CALL(*engine_ptr_,
2249 HasPermission(DocumentPermission::kPrintHighQuality))
2250 .WillRepeatedly(Return(false));
2251 EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
2252 .WillRepeatedly(Return(true));
2254 blink::WebPrintParams params;
2255 params.rasterize_pdf = true;
2256 ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
2257 plugin_->PrintBegin(params));
2261 PrintPages(ElementsAre(0),
2262 Field(&blink::WebPrintParams::rasterize_pdf, IsTrue())));
2263 plugin_->PrintPage(0, canvas_.sk_canvas());
2264 plugin_->PrintEnd();
2267 TEST_F(PdfViewWebPluginPrintTest, Disabled) {
2268 EXPECT_EQ(0, plugin_->PrintBegin(blink::WebPrintParams()));
2271 TEST_F(PdfViewWebPluginPrintTest, DisabledRasterized) {
2272 blink::WebPrintParams params;
2273 params.rasterize_pdf = true;
2274 EXPECT_EQ(0, plugin_->PrintBegin(params));
2277 class PdfViewWebPluginPrintPreviewTest : public PdfViewWebPluginTest {
2279 void SetUpClient() override {
2280 EXPECT_CALL(*client_ptr_, GetEmbedderOriginString)
2281 .WillRepeatedly(Return("chrome://print/"));
2285 TEST_F(PdfViewWebPluginPrintPreviewTest, HandleResetPrintPreviewModeMessage) {
2286 EXPECT_CALL(*client_ptr_, CreateEngine)
2287 .WillOnce([](PDFEngine::Client* client,
2288 PDFiumFormFiller::ScriptOption script_option) {
2289 EXPECT_EQ(PDFiumFormFiller::ScriptOption::kNoJavaScript, script_option);
2291 auto engine = std::make_unique<NiceMock<TestPDFiumEngine>>(client);
2292 EXPECT_CALL(*engine, ZoomUpdated);
2293 EXPECT_CALL(*engine, PageOffsetUpdated);
2294 EXPECT_CALL(*engine, PluginSizeUpdated);
2295 EXPECT_CALL(*engine, SetGrayscale(false));
2299 OnMessageWithEngineUpdate(ParseMessage(R"({
2300 "type": "resetPrintPreviewMode",
2301 "url": "chrome-untrusted://print/0/0/print.pdf",
2307 TEST_F(PdfViewWebPluginPrintPreviewTest,
2308 HandleResetPrintPreviewModeMessageForPdf) {
2309 EXPECT_CALL(*client_ptr_, CreateEngine)
2310 .WillOnce([](PDFEngine::Client* client,
2311 PDFiumFormFiller::ScriptOption script_option) {
2312 EXPECT_EQ(PDFiumFormFiller::ScriptOption::kNoJavaScript, script_option);
2314 return std::make_unique<NiceMock<TestPDFiumEngine>>(client);
2317 // The UI ID of 1 in the URL is arbitrary.
2318 // The page index value of -1, AKA `kCompletePDFIndex`, is required for PDFs.
2319 OnMessageWithEngineUpdate(ParseMessage(R"({
2320 "type": "resetPrintPreviewMode",
2321 "url": "chrome-untrusted://print/1/-1/print.pdf",
2326 EXPECT_CALL(*client_ptr_, PostMessage).Times(AnyNumber());
2327 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
2328 "type": "printPreviewLoaded",
2330 plugin_->DocumentLoadComplete();
2331 pdf_receiver_.FlushForTesting();
2334 TEST_F(PdfViewWebPluginPrintPreviewTest,
2335 HandleResetPrintPreviewModeMessageSetGrayscale) {
2336 EXPECT_CALL(*client_ptr_, CreateEngine)
2337 .WillOnce([](PDFEngine::Client* client,
2338 PDFiumFormFiller::ScriptOption /*script_option*/) {
2339 auto engine = std::make_unique<NiceMock<TestPDFiumEngine>>(client);
2340 EXPECT_CALL(*engine, SetGrayscale(true));
2344 OnMessageWithEngineUpdate(ParseMessage(R"({
2345 "type": "resetPrintPreviewMode",
2346 "url": "chrome-untrusted://print/0/0/print.pdf",
2352 TEST_F(PdfViewWebPluginPrintPreviewTest, DocumentLoadComplete) {
2353 OnMessageWithEngineUpdate(ParseMessage(R"({
2354 "type": "resetPrintPreviewMode",
2355 "url": "chrome-untrusted://print/0/0/print.pdf",
2360 EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadSuccess"));
2361 EXPECT_CALL(*client_ptr_, PostMessage);
2362 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
2363 "type": "formFocusChange",
2366 ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
2367 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
2368 "type": "printPreviewLoaded",
2370 EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
2372 EXPECT_CALL(*client_ptr_, DidStopLoading).Times(0);
2373 EXPECT_CALL(pdf_service_, UpdateContentRestrictions).Times(0);
2374 plugin_->DocumentLoadComplete();
2376 EXPECT_EQ(PdfViewWebPlugin::DocumentLoadState::kComplete,
2377 plugin_->document_load_state_for_testing());
2378 pdf_receiver_.FlushForTesting();
2381 TEST_F(PdfViewWebPluginPrintPreviewTest,
2382 DocumentLoadProgressResetByResetPrintPreviewModeMessage) {
2383 plugin_->DocumentLoadProgress(2, 100);
2385 OnMessageWithEngineUpdate(ParseMessage(R"({
2386 "type": "resetPrintPreviewMode",
2387 "url": "chrome-untrusted://print/123/0/print.pdf",
2392 EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
2393 "type": "loadProgress",
2396 plugin_->DocumentLoadProgress(3, 100);
2399 TEST_F(PdfViewWebPluginPrintPreviewTest,
2400 DocumentLoadProgressNotResetByLoadPreviewPageMessage) {
2401 OnMessageWithEngineUpdate(ParseMessage(R"({
2402 "type": "resetPrintPreviewMode",
2403 "url": "chrome-untrusted://print/123/0/print.pdf",
2408 plugin_->DocumentLoadProgress(2, 100);
2410 plugin_->OnMessage(ParseMessage(R"({
2411 "type": "loadPreviewPage",
2412 "url": "chrome-untrusted://print/123/1/print.pdf",
2416 EXPECT_CALL(*client_ptr_, PostMessage).Times(0);
2417 plugin_->DocumentLoadProgress(3, 100);
2420 TEST_F(PdfViewWebPluginPrintPreviewTest,
2421 HandleViewportMessageScrollRightToLeft) {
2422 EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout)
2423 .WillRepeatedly(Return(gfx::Size(16, 9)));
2424 EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(14));
2425 EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(3));
2427 plugin_->OnMessage(ParseMessage(R"({
2429 "userInitiated": false,
2433 "defaultPageOrientation": 0,
2434 "twoUpViewEnabled": false,
2442 } // namespace chrome_pdf