pdf_view_web_plugin_unittest.cc 81 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "pdf/pdf_view_web_plugin.h"
  5. #include <stdint.h>
  6. #include <functional>
  7. #include <memory>
  8. #include <string>
  9. #include <utility>
  10. #include <vector>
  11. #include "base/containers/span.h"
  12. #include "base/location.h"
  13. #include "base/memory/raw_ptr.h"
  14. #include "base/memory/weak_ptr.h"
  15. #include "base/run_loop.h"
  16. #include "base/strings/string_piece.h"
  17. #include "base/test/bind.h"
  18. #include "base/test/values_test_util.h"
  19. #include "base/time/time.h"
  20. #include "base/values.h"
  21. #include "cc/paint/paint_canvas.h"
  22. #include "cc/test/pixel_comparator.h"
  23. #include "cc/test/pixel_test_utils.h"
  24. #include "mojo/public/cpp/bindings/associated_receiver.h"
  25. #include "mojo/public/cpp/bindings/associated_remote.h"
  26. #include "net/cookies/site_for_cookies.h"
  27. #include "pdf/accessibility_structs.h"
  28. #include "pdf/buildflags.h"
  29. #include "pdf/content_restriction.h"
  30. #include "pdf/document_layout.h"
  31. #include "pdf/mojom/pdf.mojom.h"
  32. #include "pdf/paint_ready_rect.h"
  33. #include "pdf/pdf_accessibility_data_handler.h"
  34. #include "pdf/pdf_view_plugin_base.h"
  35. #include "pdf/test/mock_web_associated_url_loader.h"
  36. #include "pdf/test/test_helpers.h"
  37. #include "pdf/test/test_pdfium_engine.h"
  38. #include "printing/metafile_skia.h"
  39. #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
  40. #include "testing/gmock/include/gmock/gmock.h"
  41. #include "testing/gtest/include/gtest/gtest.h"
  42. #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
  43. #include "third_party/blink/public/common/input/web_input_event.h"
  44. #include "third_party/blink/public/common/input/web_keyboard_event.h"
  45. #include "third_party/blink/public/common/input/web_mouse_event.h"
  46. #include "third_party/blink/public/common/loader/http_body_element_type.h"
  47. #include "third_party/blink/public/platform/web_data.h"
  48. #include "third_party/blink/public/platform/web_http_body.h"
  49. #include "third_party/blink/public/platform/web_http_header_visitor.h"
  50. #include "third_party/blink/public/platform/web_input_event_result.h"
  51. #include "third_party/blink/public/platform/web_string.h"
  52. #include "third_party/blink/public/platform/web_text_input_type.h"
  53. #include "third_party/blink/public/platform/web_url.h"
  54. #include "third_party/blink/public/platform/web_url_request.h"
  55. #include "third_party/blink/public/platform/web_url_response.h"
  56. #include "third_party/blink/public/web/web_associated_url_loader.h"
  57. #include "third_party/blink/public/web/web_associated_url_loader_client.h"
  58. #include "third_party/blink/public/web/web_plugin_container.h"
  59. #include "third_party/blink/public/web/web_plugin_params.h"
  60. #include "third_party/blink/public/web/web_print_params.h"
  61. #include "third_party/skia/include/core/SkBitmap.h"
  62. #include "third_party/skia/include/core/SkCanvas.h"
  63. #include "third_party/skia/include/core/SkColor.h"
  64. #include "third_party/skia/include/core/SkRefCnt.h"
  65. #include "third_party/skia/include/core/SkSurface.h"
  66. #include "ui/base/cursor/cursor.h"
  67. #include "ui/events/blink/blink_event_util.h"
  68. #include "ui/events/keycodes/dom/dom_code.h"
  69. #include "ui/events/keycodes/dom/dom_key.h"
  70. #include "ui/gfx/canvas.h"
  71. #include "ui/gfx/geometry/point.h"
  72. #include "ui/gfx/geometry/point_f.h"
  73. #include "ui/gfx/geometry/rect.h"
  74. #include "ui/gfx/geometry/size.h"
  75. #include "ui/gfx/geometry/skia_conversions.h"
  76. #include "ui/gfx/geometry/vector2d_f.h"
  77. #include "ui/gfx/range/range.h"
  78. #include "ui/latency/latency_info.h"
  79. #include "url/gurl.h"
  80. namespace chrome_pdf {
  81. namespace {
  82. using ::testing::AnyNumber;
  83. using ::testing::ElementsAre;
  84. using ::testing::ElementsAreArray;
  85. using ::testing::Eq;
  86. using ::testing::InSequence;
  87. using ::testing::Invoke;
  88. using ::testing::IsEmpty;
  89. using ::testing::IsFalse;
  90. using ::testing::IsTrue;
  91. using ::testing::MockFunction;
  92. using ::testing::NiceMock;
  93. using ::testing::Pointwise;
  94. using ::testing::Return;
  95. using ::testing::SaveArg;
  96. using ::testing::SizeIs;
  97. // `kCanvasSize` needs to be big enough to hold plugin's snapshots during
  98. // testing.
  99. constexpr gfx::Size kCanvasSize(100, 100);
  100. // Note: Make sure `kDefaultColor` is different from `kPaintColor` and the
  101. // plugin's background color. This will help identify bitmap changes after
  102. // painting.
  103. constexpr SkColor kDefaultColor = SK_ColorGREEN;
  104. constexpr SkColor kPaintColor = SK_ColorRED;
  105. struct PaintParams {
  106. // The plugin container's device scale.
  107. float device_scale;
  108. // The window area in CSS pixels.
  109. gfx::Rect window_rect;
  110. // The target painting area on the canvas in CSS pixels.
  111. gfx::Rect paint_rect;
  112. // The expected clipped area to be filled with paint color. The clipped area
  113. // should be the intersection of `paint_rect` and `window_rect`.
  114. gfx::Rect expected_clipped_rect;
  115. };
  116. MATCHER(SearchStringResultEq, "") {
  117. PDFEngine::Client::SearchStringResult l = std::get<0>(arg);
  118. PDFEngine::Client::SearchStringResult r = std::get<1>(arg);
  119. return l.start_index == r.start_index && l.length == r.length;
  120. }
  121. MATCHER_P(IsExpectedImeKeyEvent, expected_text, "") {
  122. if (arg.GetType() != blink::WebInputEvent::Type::kChar)
  123. return false;
  124. const auto& event = static_cast<const blink::WebKeyboardEvent&>(arg);
  125. return event.GetModifiers() == blink::WebInputEvent::kNoModifiers &&
  126. event.windows_key_code == expected_text[0] &&
  127. event.native_key_code == expected_text[0] &&
  128. event.dom_code == static_cast<int>(ui::DomCode::NONE) &&
  129. event.dom_key == ui::DomKey::NONE && !event.is_system_key &&
  130. !event.is_browser_shortcut && event.text == expected_text &&
  131. event.unmodified_text == expected_text;
  132. }
  133. base::Value::Dict ParseMessage(base::StringPiece json) {
  134. return std::move(base::test::ParseJson(json).GetDict());
  135. }
  136. // Generates the expected `SkBitmap` with `paint_color` filled in the expected
  137. // clipped area and `kDefaultColor` as the background color.
  138. SkBitmap GenerateExpectedBitmapForPaint(const gfx::Rect& expected_clipped_rect,
  139. SkColor paint_color) {
  140. sk_sp<SkSurface> expected_surface =
  141. CreateSkiaSurfaceForTesting(kCanvasSize, kDefaultColor);
  142. expected_surface->getCanvas()->clipIRect(
  143. gfx::RectToSkIRect(expected_clipped_rect));
  144. expected_surface->getCanvas()->clear(paint_color);
  145. SkBitmap expected_bitmap;
  146. expected_surface->makeImageSnapshot()->asLegacyBitmap(&expected_bitmap);
  147. return expected_bitmap;
  148. }
  149. class MockHeaderVisitor : public blink::WebHTTPHeaderVisitor {
  150. public:
  151. MOCK_METHOD(void,
  152. VisitHeader,
  153. (const blink::WebString&, const blink::WebString&),
  154. (override));
  155. };
  156. class MockPdfAccessibilityDataHandler : public PdfAccessibilityDataHandler {
  157. public:
  158. // PdfAccessibilityDataHandler:
  159. MOCK_METHOD(void,
  160. SetAccessibilityViewportInfo,
  161. (AccessibilityViewportInfo),
  162. (override));
  163. MOCK_METHOD(void,
  164. SetAccessibilityDocInfo,
  165. (AccessibilityDocInfo),
  166. (override));
  167. MOCK_METHOD(void,
  168. SetAccessibilityPageInfo,
  169. (AccessibilityPageInfo,
  170. std::vector<AccessibilityTextRunInfo>,
  171. std::vector<AccessibilityCharInfo>,
  172. AccessibilityPageObjects),
  173. (override));
  174. };
  175. class FakePdfViewWebPluginClient : public PdfViewWebPlugin::Client {
  176. public:
  177. FakePdfViewWebPluginClient() {
  178. ON_CALL(*this, CreateAssociatedURLLoader).WillByDefault([]() {
  179. auto associated_loader =
  180. std::make_unique<NiceMock<MockWebAssociatedURLLoader>>();
  181. ON_CALL(*associated_loader, LoadAsynchronously)
  182. .WillByDefault([](const blink::WebURLRequest& /*request*/,
  183. blink::WebAssociatedURLLoaderClient* client) {
  184. // TODO(crbug.com/1322928): Must trigger callback to free
  185. // `UrlLoader`.
  186. client->DidReceiveResponse(blink::WebURLResponse());
  187. client->DidFinishLoading();
  188. });
  189. return associated_loader;
  190. });
  191. ON_CALL(*this, GetEmbedderOriginString)
  192. .WillByDefault(
  193. Return("chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/"));
  194. ON_CALL(*this, HasFrame).WillByDefault(Return(true));
  195. }
  196. // PdfViewWebPlugin::Client:
  197. MOCK_METHOD(std::unique_ptr<base::Value>,
  198. FromV8Value,
  199. (v8::Local<v8::Value>, v8::Local<v8::Context>),
  200. (override));
  201. MOCK_METHOD(base::WeakPtr<Client>, GetWeakPtr, (), (override));
  202. MOCK_METHOD(std::unique_ptr<PDFiumEngine>,
  203. CreateEngine,
  204. (PDFEngine::Client*, PDFiumFormFiller::ScriptOption),
  205. (override));
  206. MOCK_METHOD(void,
  207. SetPluginContainer,
  208. (blink::WebPluginContainer*),
  209. (override));
  210. MOCK_METHOD(blink::WebPluginContainer*, PluginContainer, (), (override));
  211. MOCK_METHOD(net::SiteForCookies, SiteForCookies, (), (const override));
  212. MOCK_METHOD(blink::WebURL,
  213. CompleteURL,
  214. (const blink::WebString&),
  215. (const override));
  216. MOCK_METHOD(void, PostMessage, (base::Value::Dict), (override));
  217. MOCK_METHOD(void, Invalidate, (), (override));
  218. MOCK_METHOD(void,
  219. RequestTouchEventType,
  220. (blink::WebPluginContainer::TouchEventRequestType),
  221. (override));
  222. MOCK_METHOD(void, ReportFindInPageMatchCount, (int, int, bool), (override));
  223. MOCK_METHOD(void, ReportFindInPageSelection, (int, int, bool), (override));
  224. MOCK_METHOD(void,
  225. ReportFindInPageTickmarks,
  226. (const std::vector<gfx::Rect>&),
  227. (override));
  228. MOCK_METHOD(float, DeviceScaleFactor, (), (override));
  229. MOCK_METHOD(gfx::PointF, GetScrollPosition, (), (override));
  230. MOCK_METHOD(void, UsePluginAsFindHandler, (), (override));
  231. MOCK_METHOD(void,
  232. SetReferrerForRequest,
  233. (blink::WebURLRequest&, const blink::WebURL&),
  234. (override));
  235. MOCK_METHOD(void, Alert, (const blink::WebString&), (override));
  236. MOCK_METHOD(bool, Confirm, (const blink::WebString&), (override));
  237. MOCK_METHOD(blink::WebString,
  238. Prompt,
  239. (const blink::WebString&, const blink::WebString&),
  240. (override));
  241. MOCK_METHOD(void,
  242. TextSelectionChanged,
  243. (const blink::WebString&, uint32_t, const gfx::Range&),
  244. (override));
  245. MOCK_METHOD(std::unique_ptr<blink::WebAssociatedURLLoader>,
  246. CreateAssociatedURLLoader,
  247. (const blink::WebAssociatedURLLoaderOptions&),
  248. (override));
  249. MOCK_METHOD(void, UpdateTextInputState, (), (override));
  250. MOCK_METHOD(void, UpdateSelectionBounds, (), (override));
  251. MOCK_METHOD(std::string, GetEmbedderOriginString, (), (override));
  252. MOCK_METHOD(bool, HasFrame, (), (const override));
  253. MOCK_METHOD(void, DidStartLoading, (), (override));
  254. MOCK_METHOD(void, DidStopLoading, (), (override));
  255. MOCK_METHOD(void, RecordComputedAction, (const std::string&), (override));
  256. MOCK_METHOD(std::unique_ptr<PdfAccessibilityDataHandler>,
  257. CreateAccessibilityDataHandler,
  258. (PdfAccessibilityActionHandler*),
  259. (override));
  260. };
  261. class FakePdfService : public pdf::mojom::PdfService {
  262. public:
  263. MOCK_METHOD(void,
  264. SetListener,
  265. (mojo::PendingRemote<pdf::mojom::PdfListener>),
  266. (override));
  267. MOCK_METHOD(void, UpdateContentRestrictions, (int32_t), (override));
  268. MOCK_METHOD(void, HasUnsupportedFeature, (), (override));
  269. MOCK_METHOD(void,
  270. SaveUrlAs,
  271. (const GURL&, network::mojom::ReferrerPolicy),
  272. (override));
  273. MOCK_METHOD(void,
  274. SelectionChanged,
  275. (const gfx::PointF&, int32_t, const gfx::PointF&, int32_t),
  276. (override));
  277. MOCK_METHOD(void, SetPluginCanSave, (bool), (override));
  278. };
  279. } // namespace
  280. class PdfViewWebPluginWithoutInitializeTest : public testing::Test {
  281. protected:
  282. // Custom deleter for `plugin_`. PdfViewWebPlugin must be destroyed by
  283. // PdfViewWebPlugin::Destroy() instead of its destructor.
  284. struct PluginDeleter {
  285. void operator()(PdfViewWebPlugin* ptr) { ptr->Destroy(); }
  286. };
  287. static void AddToPluginParams(base::StringPiece name,
  288. base::StringPiece value,
  289. blink::WebPluginParams& params) {
  290. params.attribute_names.push_back(
  291. blink::WebString::FromUTF8(name.data(), name.size()));
  292. params.attribute_values.push_back(
  293. blink::WebString::FromUTF8(value.data(), value.size()));
  294. }
  295. void SetUpPlugin(base::StringPiece document_url,
  296. const blink::WebPluginParams& params) {
  297. auto client = std::make_unique<NiceMock<FakePdfViewWebPluginClient>>();
  298. client_ptr_ = client.get();
  299. ON_CALL(*client_ptr_, CompleteURL)
  300. .WillByDefault([parsed_document_url = GURL(document_url)](
  301. const blink::WebString& partial_url) {
  302. return parsed_document_url.Resolve(partial_url.Utf8());
  303. });
  304. ON_CALL(*client_ptr_, CreateEngine)
  305. .WillByDefault([this](
  306. PDFEngine::Client* client,
  307. PDFiumFormFiller::ScriptOption /*script_option*/) {
  308. auto engine = std::make_unique<NiceMock<TestPDFiumEngine>>(client);
  309. engine_ptr_ = engine.get();
  310. return engine;
  311. });
  312. ON_CALL(*client_ptr_, CreateAccessibilityDataHandler)
  313. .WillByDefault([this]() {
  314. auto handler =
  315. std::make_unique<NiceMock<MockPdfAccessibilityDataHandler>>();
  316. accessibility_data_handler_ptr_ = handler.get();
  317. return handler;
  318. });
  319. SetUpClient();
  320. plugin_ =
  321. std::unique_ptr<PdfViewWebPlugin, PluginDeleter>(new PdfViewWebPlugin(
  322. std::move(client),
  323. mojo::AssociatedRemote<pdf::mojom::PdfService>(
  324. pdf_receiver_.BindNewEndpointAndPassDedicatedRemote()),
  325. params));
  326. }
  327. void SetUpPluginWithUrl(const std::string& url) {
  328. blink::WebPluginParams params;
  329. AddToPluginParams("src", url, params);
  330. SetUpPluginParams(params);
  331. SetUpPlugin(url, params);
  332. }
  333. // Allows derived classes to customize plugin parameters within
  334. // `SetUpPluginWithUrl()`.
  335. virtual void SetUpPluginParams(blink::WebPluginParams& params) {}
  336. // Allows derived classes to customize `client_ptr_` within `SetUpPlugin()`.
  337. virtual void SetUpClient() {}
  338. void TearDown() override { plugin_.reset(); }
  339. void ExpectUpdateTextInputState(
  340. blink::WebTextInputType expected_text_input_type) {
  341. EXPECT_CALL(*client_ptr_, UpdateTextInputState)
  342. .WillOnce([this, expected_text_input_type]() {
  343. EXPECT_EQ(expected_text_input_type,
  344. plugin_->GetPluginTextInputType());
  345. });
  346. }
  347. NiceMock<FakePdfService> pdf_service_;
  348. mojo::AssociatedReceiver<pdf::mojom::PdfService> pdf_receiver_{&pdf_service_};
  349. raw_ptr<FakePdfViewWebPluginClient> client_ptr_;
  350. std::unique_ptr<PdfViewWebPlugin, PluginDeleter> plugin_;
  351. raw_ptr<TestPDFiumEngine> engine_ptr_;
  352. raw_ptr<MockPdfAccessibilityDataHandler> accessibility_data_handler_ptr_;
  353. };
  354. class PdfViewWebPluginTest : public PdfViewWebPluginWithoutInitializeTest {
  355. protected:
  356. static constexpr char kPdfUrl[] = "http://localhost/example.pdf";
  357. void SetUp() override {
  358. SetUpPluginWithUrl(kPdfUrl);
  359. EXPECT_TRUE(plugin_->InitializeForTesting());
  360. }
  361. void SetDocumentDimensions(const gfx::Size& dimensions) {
  362. EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout)
  363. .WillRepeatedly(Return(dimensions));
  364. SendViewportMessage(/*zoom=*/1.0);
  365. }
  366. void SendViewportMessage(double zoom) {
  367. base::Value::Dict message = ParseMessage(R"({
  368. "type": "viewport",
  369. "userInitiated": false,
  370. "zoom": 1,
  371. "layoutOptions": {
  372. "direction": 2,
  373. "defaultPageOrientation": 0,
  374. "twoUpViewEnabled": false,
  375. },
  376. "xOffset": 0,
  377. "yOffset": 0,
  378. "pinchPhase": 0,
  379. })");
  380. message.Set("zoom", zoom);
  381. plugin_->OnMessage(message);
  382. }
  383. void UpdatePluginGeometry(float device_scale, const gfx::Rect& window_rect) {
  384. UpdatePluginGeometryWithoutWaiting(device_scale, window_rect);
  385. // Waits for main thread callback scheduled by `PaintManager`.
  386. base::RunLoop run_loop;
  387. base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
  388. run_loop.QuitClosure());
  389. run_loop.Run();
  390. }
  391. void UpdatePluginGeometryWithoutWaiting(float device_scale,
  392. const gfx::Rect& window_rect) {
  393. // The plugin container's device scale must be set before calling
  394. // UpdateGeometry().
  395. EXPECT_CALL(*client_ptr_, DeviceScaleFactor)
  396. .WillRepeatedly(Return(device_scale));
  397. plugin_->UpdateGeometry(window_rect, window_rect, window_rect,
  398. /*is_visible=*/true);
  399. }
  400. void TestUpdateGeometrySetsPluginRect(float device_scale,
  401. const gfx::Rect& window_rect,
  402. float expected_device_scale,
  403. const gfx::Rect& expected_plugin_rect) {
  404. UpdatePluginGeometryWithoutWaiting(device_scale, window_rect);
  405. EXPECT_EQ(expected_device_scale, plugin_->GetDeviceScaleForTesting())
  406. << "Device scale comparison failure at device scale of "
  407. << device_scale;
  408. EXPECT_EQ(expected_plugin_rect, plugin_->GetPluginRectForTesting())
  409. << "Plugin rect comparison failure at device scale of " << device_scale
  410. << ", window rect of " << window_rect.ToString();
  411. }
  412. void TestPaintEmptySnapshots(float device_scale,
  413. const gfx::Rect& window_rect,
  414. const gfx::Rect& paint_rect,
  415. const gfx::Rect& expected_clipped_rect) {
  416. UpdatePluginGeometryWithoutWaiting(device_scale, window_rect);
  417. canvas_.DrawColor(kDefaultColor);
  418. plugin_->Paint(canvas_.sk_canvas(), paint_rect);
  419. // Expect the clipped area on canvas to be filled with plugin's background
  420. // color.
  421. SkBitmap expected_bitmap = GenerateExpectedBitmapForPaint(
  422. expected_clipped_rect, plugin_->GetBackgroundColor());
  423. EXPECT_TRUE(
  424. cc::MatchesBitmap(canvas_.GetBitmap(), expected_bitmap,
  425. cc::ExactPixelComparator(/*discard_alpha=*/false)))
  426. << "Failure at device scale of " << device_scale << ", window rect of "
  427. << window_rect.ToString();
  428. }
  429. void TestPaintSnapshots(float device_scale,
  430. const gfx::Rect& window_rect,
  431. const gfx::Rect& paint_rect,
  432. const gfx::Rect& expected_clipped_rect) {
  433. UpdatePluginGeometry(device_scale, window_rect);
  434. canvas_.DrawColor(kDefaultColor);
  435. // Paint the plugin with `kPaintColor`.
  436. plugin_->UpdateSnapshot(CreateSkiaImageForTesting(
  437. plugin_->GetPluginRectForTesting().size(), kPaintColor));
  438. plugin_->Paint(canvas_.sk_canvas(), paint_rect);
  439. // Expect the clipped area on canvas to be filled with `kPaintColor`.
  440. SkBitmap expected_bitmap =
  441. GenerateExpectedBitmapForPaint(expected_clipped_rect, kPaintColor);
  442. EXPECT_TRUE(
  443. cc::MatchesBitmap(canvas_.GetBitmap(), expected_bitmap,
  444. cc::ExactPixelComparator(/*discard_alpha=*/false)))
  445. << "Failure at device scale of " << device_scale << ", window rect of "
  446. << window_rect.ToString();
  447. }
  448. // Provides the cc::PaintCanvas for painting.
  449. gfx::Canvas canvas_{kCanvasSize, /*image_scale=*/1.0f, /*is_opaque=*/true};
  450. };
  451. class PdfViewWebPluginFullFrameTest : public PdfViewWebPluginTest {
  452. protected:
  453. void SetUpPluginParams(blink::WebPluginParams& params) override {
  454. AddToPluginParams("full-frame", "full-frame", params);
  455. }
  456. };
  457. TEST_F(PdfViewWebPluginWithoutInitializeTest, Initialize) {
  458. SetUpPluginWithUrl("http://localhost/example.pdf");
  459. EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader)
  460. .WillOnce([](const blink::WebAssociatedURLLoaderOptions& options) {
  461. EXPECT_TRUE(options.grant_universal_access);
  462. auto associated_loader =
  463. std::make_unique<NiceMock<MockWebAssociatedURLLoader>>();
  464. EXPECT_CALL(*associated_loader, LoadAsynchronously)
  465. .WillOnce([](const blink::WebURLRequest& request,
  466. blink::WebAssociatedURLLoaderClient* client) {
  467. EXPECT_EQ("http://localhost/example.pdf",
  468. request.Url().GetString().Utf8());
  469. EXPECT_EQ("GET", request.HttpMethod().Utf8());
  470. EXPECT_TRUE(request.HttpBody().IsNull());
  471. NiceMock<MockHeaderVisitor> header_visitor;
  472. EXPECT_CALL(header_visitor, VisitHeader).Times(0);
  473. request.VisitHttpHeaderFields(&header_visitor);
  474. EXPECT_FALSE(client->WillFollowRedirect(blink::WebURL(),
  475. blink::WebURLResponse()));
  476. client->DidReceiveResponse(blink::WebURLResponse());
  477. client->DidFinishLoading();
  478. });
  479. return associated_loader;
  480. });
  481. EXPECT_CALL(*client_ptr_, SetReferrerForRequest).Times(0);
  482. EXPECT_TRUE(plugin_->InitializeForTesting());
  483. }
  484. TEST_F(PdfViewWebPluginWithoutInitializeTest, InitializeWithEmptyUrl) {
  485. SetUpPluginWithUrl("");
  486. EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader).Times(0);
  487. EXPECT_FALSE(plugin_->InitializeForTesting());
  488. }
  489. TEST_F(PdfViewWebPluginWithoutInitializeTest, InitializeForPrintPreview) {
  490. SetUpPluginWithUrl("about:blank");
  491. EXPECT_CALL(*client_ptr_, GetEmbedderOriginString)
  492. .WillRepeatedly(Return("chrome://print/"));
  493. EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader).Times(0);
  494. EXPECT_TRUE(plugin_->InitializeForTesting());
  495. }
  496. TEST_F(PdfViewWebPluginTest, CreateUrlLoader) {
  497. EXPECT_CALL(*client_ptr_, DidStartLoading).Times(0);
  498. EXPECT_CALL(pdf_service_, UpdateContentRestrictions).Times(0);
  499. plugin_->CreateUrlLoader();
  500. EXPECT_EQ(PdfViewPluginBase::DocumentLoadState::kLoading,
  501. plugin_->document_load_state_for_testing());
  502. pdf_receiver_.FlushForTesting();
  503. }
  504. TEST_F(PdfViewWebPluginFullFrameTest, CreateUrlLoader) {
  505. EXPECT_CALL(*client_ptr_, DidStartLoading);
  506. EXPECT_CALL(pdf_service_,
  507. UpdateContentRestrictions(kContentRestrictionSave |
  508. kContentRestrictionPrint));
  509. plugin_->CreateUrlLoader();
  510. EXPECT_EQ(PdfViewPluginBase::DocumentLoadState::kLoading,
  511. plugin_->document_load_state_for_testing());
  512. pdf_receiver_.FlushForTesting();
  513. }
  514. TEST_F(PdfViewWebPluginFullFrameTest, CreateUrlLoaderMultipleTimes) {
  515. plugin_->CreateUrlLoader();
  516. EXPECT_CALL(*client_ptr_, DidStartLoading).Times(0);
  517. plugin_->CreateUrlLoader();
  518. }
  519. TEST_F(PdfViewWebPluginFullFrameTest, CreateUrlLoaderAfterDocumentLoadFailed) {
  520. plugin_->CreateUrlLoader();
  521. plugin_->DocumentLoadFailed();
  522. EXPECT_CALL(*client_ptr_, DidStartLoading);
  523. plugin_->CreateUrlLoader();
  524. }
  525. TEST_F(PdfViewWebPluginTest, DocumentLoadComplete) {
  526. plugin_->CreateUrlLoader();
  527. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadSuccess"));
  528. EXPECT_CALL(*client_ptr_, PostMessage);
  529. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  530. "type": "formFocusChange",
  531. "focused": false,
  532. })")));
  533. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  534. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  535. "type": "printPreviewLoaded",
  536. })")))
  537. .Times(0);
  538. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
  539. .Times(0);
  540. EXPECT_CALL(*client_ptr_, DidStopLoading).Times(0);
  541. EXPECT_CALL(pdf_service_, UpdateContentRestrictions).Times(0);
  542. plugin_->DocumentLoadComplete();
  543. EXPECT_EQ(PdfViewPluginBase::DocumentLoadState::kComplete,
  544. plugin_->document_load_state_for_testing());
  545. pdf_receiver_.FlushForTesting();
  546. }
  547. TEST_F(PdfViewWebPluginFullFrameTest, DocumentLoadComplete) {
  548. // Must flush IPCs after `CreateUrlLoader()` in full-frame mode, otherwise
  549. // there's an unexpected `UpdateContentRestrictions()` call (see the
  550. // `PdfViewWebPluginFullFrameTest.CreateUrlLoader` test).
  551. plugin_->CreateUrlLoader();
  552. pdf_receiver_.FlushForTesting();
  553. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadSuccess"));
  554. EXPECT_CALL(*client_ptr_, PostMessage);
  555. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  556. "type": "formFocusChange",
  557. "focused": false,
  558. })")));
  559. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  560. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  561. "type": "printPreviewLoaded",
  562. })")))
  563. .Times(0);
  564. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
  565. .Times(0);
  566. EXPECT_CALL(*client_ptr_, DidStopLoading);
  567. EXPECT_CALL(pdf_service_, UpdateContentRestrictions(kContentRestrictionPrint |
  568. kContentRestrictionPaste |
  569. kContentRestrictionCut |
  570. kContentRestrictionCopy));
  571. plugin_->DocumentLoadComplete();
  572. EXPECT_EQ(PdfViewPluginBase::DocumentLoadState::kComplete,
  573. plugin_->document_load_state_for_testing());
  574. pdf_receiver_.FlushForTesting();
  575. }
  576. TEST_F(PdfViewWebPluginTest, DocumentLoadFailed) {
  577. plugin_->CreateUrlLoader();
  578. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadFailure"));
  579. EXPECT_CALL(*client_ptr_, DidStopLoading).Times(0);
  580. plugin_->DocumentLoadFailed();
  581. EXPECT_EQ(PdfViewPluginBase::DocumentLoadState::kFailed,
  582. plugin_->document_load_state_for_testing());
  583. }
  584. TEST_F(PdfViewWebPluginFullFrameTest, DocumentLoadFailed) {
  585. plugin_->CreateUrlLoader();
  586. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadFailure"));
  587. EXPECT_CALL(*client_ptr_, DidStopLoading);
  588. plugin_->DocumentLoadFailed();
  589. EXPECT_EQ(PdfViewPluginBase::DocumentLoadState::kFailed,
  590. plugin_->document_load_state_for_testing());
  591. }
  592. TEST_F(PdfViewWebPluginTest, DocumentHasUnsupportedFeature) {
  593. EXPECT_CALL(*client_ptr_, RecordComputedAction).Times(AnyNumber());
  594. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature1"));
  595. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature2"));
  596. // `HasUnsupportedFeature()` is not called if the viewer is not full-frame.
  597. EXPECT_CALL(pdf_service_, HasUnsupportedFeature).Times(0);
  598. plugin_->DocumentHasUnsupportedFeature("feature1");
  599. plugin_->DocumentHasUnsupportedFeature("feature2");
  600. pdf_receiver_.FlushForTesting();
  601. }
  602. TEST_F(PdfViewWebPluginTest, DocumentHasUnsupportedFeatureWithRepeatedFeature) {
  603. // Metrics should only be recorded once per feature.
  604. EXPECT_CALL(*client_ptr_, RecordComputedAction).Times(AnyNumber());
  605. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature"));
  606. // `HasUnsupportedFeature()` is not called if the viewer is not full-frame.
  607. EXPECT_CALL(pdf_service_, HasUnsupportedFeature).Times(0);
  608. plugin_->DocumentHasUnsupportedFeature("feature");
  609. plugin_->DocumentHasUnsupportedFeature("feature");
  610. pdf_receiver_.FlushForTesting();
  611. }
  612. TEST_F(PdfViewWebPluginFullFrameTest, DocumentHasUnsupportedFeature) {
  613. EXPECT_CALL(*client_ptr_, RecordComputedAction).Times(AnyNumber());
  614. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature1"));
  615. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature2"));
  616. // `HasUnsupportedFeature()` is called once for all features.
  617. EXPECT_CALL(pdf_service_, HasUnsupportedFeature);
  618. plugin_->DocumentHasUnsupportedFeature("feature1");
  619. plugin_->DocumentHasUnsupportedFeature("feature2");
  620. pdf_receiver_.FlushForTesting();
  621. }
  622. TEST_F(PdfViewWebPluginFullFrameTest,
  623. DocumentHasUnsupportedFeatureWithRepeatedFeature) {
  624. // Metrics should only be recorded once per feature.
  625. EXPECT_CALL(*client_ptr_, RecordComputedAction).Times(AnyNumber());
  626. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF_Unsupported_feature"));
  627. // `HasUnsupportedFeature()` is called once for all features.
  628. EXPECT_CALL(pdf_service_, HasUnsupportedFeature);
  629. plugin_->DocumentHasUnsupportedFeature("feature");
  630. plugin_->DocumentHasUnsupportedFeature("feature");
  631. pdf_receiver_.FlushForTesting();
  632. }
  633. TEST_F(PdfViewWebPluginTest, DocumentLoadProgress) {
  634. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  635. "type": "loadProgress",
  636. "progress": 5.0,
  637. })")));
  638. plugin_->DocumentLoadProgress(10, 200);
  639. }
  640. TEST_F(PdfViewWebPluginTest, DocumentLoadProgressIgnoreSmall) {
  641. plugin_->DocumentLoadProgress(2, 100);
  642. EXPECT_CALL(*client_ptr_, PostMessage).Times(0);
  643. plugin_->DocumentLoadProgress(3, 100);
  644. }
  645. TEST_F(PdfViewWebPluginTest, DocumentLoadProgressMultipleSmall) {
  646. plugin_->DocumentLoadProgress(2, 100);
  647. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  648. "type": "loadProgress",
  649. "progress": 4.0,
  650. })")));
  651. plugin_->DocumentLoadProgress(3, 100);
  652. plugin_->DocumentLoadProgress(4, 100);
  653. }
  654. TEST_F(PdfViewWebPluginTest, EnableAccessibilityBeforeDocumentLoadComplete) {
  655. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
  656. .Times(0);
  657. plugin_->EnableAccessibility();
  658. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
  659. plugin_->CreateUrlLoader();
  660. plugin_->DocumentLoadComplete();
  661. }
  662. TEST_F(PdfViewWebPluginTest,
  663. EnableAccessibilityBeforeDocumentLoadCompleteRepeated) {
  664. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
  665. .Times(0);
  666. plugin_->EnableAccessibility();
  667. plugin_->EnableAccessibility();
  668. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
  669. plugin_->CreateUrlLoader();
  670. plugin_->DocumentLoadComplete();
  671. }
  672. TEST_F(PdfViewWebPluginTest, EnableAccessibilityAfterDocumentLoadComplete) {
  673. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
  674. .Times(0);
  675. plugin_->CreateUrlLoader();
  676. plugin_->DocumentLoadComplete();
  677. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo);
  678. plugin_->EnableAccessibility();
  679. }
  680. TEST_F(PdfViewWebPluginTest,
  681. EnableAccessibilityAfterDocumentLoadCompleteRepeated) {
  682. plugin_->CreateUrlLoader();
  683. plugin_->DocumentLoadComplete();
  684. plugin_->EnableAccessibility();
  685. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
  686. .Times(0);
  687. plugin_->EnableAccessibility();
  688. }
  689. TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithNoPermissions) {
  690. EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut |
  691. kContentRestrictionPaste | kContentRestrictionPrint,
  692. plugin_->GetContentRestrictions());
  693. EXPECT_FALSE(plugin_->CanCopy());
  694. }
  695. TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithCopyAllowed) {
  696. EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
  697. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
  698. .WillRepeatedly(Return(true));
  699. EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste |
  700. kContentRestrictionPrint,
  701. plugin_->GetContentRestrictions());
  702. EXPECT_TRUE(plugin_->CanCopy());
  703. }
  704. TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithPrintLowQualityAllowed) {
  705. EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
  706. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
  707. .WillRepeatedly(Return(true));
  708. EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut |
  709. kContentRestrictionPaste,
  710. plugin_->GetContentRestrictions());
  711. }
  712. TEST_F(PdfViewWebPluginTest,
  713. GetContentRestrictionsWithCopyAndPrintLowQualityAllowed) {
  714. EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
  715. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
  716. .WillRepeatedly(Return(true));
  717. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
  718. .WillRepeatedly(Return(true));
  719. EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste,
  720. plugin_->GetContentRestrictions());
  721. }
  722. TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithPrintAllowed) {
  723. EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
  724. EXPECT_CALL(*engine_ptr_,
  725. HasPermission(DocumentPermission::kPrintHighQuality))
  726. .WillRepeatedly(Return(true));
  727. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
  728. .WillRepeatedly(Return(true));
  729. EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut |
  730. kContentRestrictionPaste,
  731. plugin_->GetContentRestrictions());
  732. }
  733. TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithCopyAndPrintAllowed) {
  734. EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
  735. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
  736. .WillRepeatedly(Return(true));
  737. EXPECT_CALL(*engine_ptr_,
  738. HasPermission(DocumentPermission::kPrintHighQuality))
  739. .WillRepeatedly(Return(true));
  740. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
  741. .WillRepeatedly(Return(true));
  742. EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste,
  743. plugin_->GetContentRestrictions());
  744. }
  745. TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithNoPermissions) {
  746. AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo();
  747. EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
  748. EXPECT_FALSE(doc_info.text_accessible);
  749. EXPECT_FALSE(doc_info.text_copyable);
  750. }
  751. TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithCopyAllowed) {
  752. EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
  753. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
  754. .WillRepeatedly(Return(true));
  755. AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo();
  756. EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
  757. EXPECT_FALSE(doc_info.text_accessible);
  758. EXPECT_TRUE(doc_info.text_copyable);
  759. }
  760. TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithCopyAccessibleAllowed) {
  761. EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
  762. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopyAccessible))
  763. .WillRepeatedly(Return(true));
  764. AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo();
  765. EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
  766. EXPECT_TRUE(doc_info.text_accessible);
  767. EXPECT_FALSE(doc_info.text_copyable);
  768. }
  769. TEST_F(PdfViewWebPluginTest,
  770. GetAccessibilityDocInfoWithCopyAndCopyAccessibleAllowed) {
  771. EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
  772. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
  773. .WillRepeatedly(Return(true));
  774. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopyAccessible))
  775. .WillRepeatedly(Return(true));
  776. AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo();
  777. EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
  778. EXPECT_TRUE(doc_info.text_accessible);
  779. EXPECT_TRUE(doc_info.text_copyable);
  780. }
  781. TEST_F(PdfViewWebPluginTest, UpdateGeometrySetsPluginRect) {
  782. EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f));
  783. TestUpdateGeometrySetsPluginRect(
  784. /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(4, 4, 12, 12),
  785. /*expected_device_scale=*/2.0f,
  786. /*expected_plugin_rect=*/gfx::Rect(4, 4, 12, 12));
  787. }
  788. TEST_F(PdfViewWebPluginTest,
  789. UpdateGeometrySetsPluginRectOnVariousDeviceScales) {
  790. struct UpdateGeometryParams {
  791. // The plugin container's device scale.
  792. float device_scale;
  793. // The window rect in CSS pixels.
  794. gfx::Rect window_rect;
  795. // The expected plugin device scale.
  796. float expected_device_scale;
  797. // The expected plugin rect in device pixels.
  798. gfx::Rect expected_plugin_rect;
  799. };
  800. static constexpr UpdateGeometryParams kUpdateGeometryParams[] = {
  801. {1.0f, gfx::Rect(3, 4, 5, 6), 1.0f, gfx::Rect(3, 4, 5, 6)},
  802. {2.0f, gfx::Rect(3, 4, 5, 6), 2.0f, gfx::Rect(3, 4, 5, 6)},
  803. };
  804. for (const auto& params : kUpdateGeometryParams) {
  805. TestUpdateGeometrySetsPluginRect(params.device_scale, params.window_rect,
  806. params.expected_device_scale,
  807. params.expected_plugin_rect);
  808. }
  809. }
  810. TEST_F(PdfViewWebPluginTest, UpdateGeometrySetsPluginRectWithEmptyWindow) {
  811. EXPECT_CALL(*engine_ptr_, ZoomUpdated).Times(0);
  812. TestUpdateGeometrySetsPluginRect(
  813. /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(2, 2, 0, 0),
  814. /*expected_device_scale=*/1.0f, /*expected_plugin_rect=*/gfx::Rect());
  815. }
  816. TEST_F(PdfViewWebPluginTest, UpdateGeometryScroll) {
  817. SetDocumentDimensions({100, 200});
  818. EXPECT_CALL(*client_ptr_, GetScrollPosition)
  819. .WillRepeatedly(Return(gfx::PointF(4.0f, 6.0f)));
  820. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(4));
  821. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(6));
  822. UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
  823. }
  824. TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollStopped) {
  825. SetDocumentDimensions({100, 200});
  826. plugin_->OnMessage(ParseMessage(R"({
  827. "type": "stopScrolling",
  828. })"));
  829. EXPECT_CALL(*client_ptr_, GetScrollPosition)
  830. .WillRepeatedly(Return(gfx::PointF(4.0f, 6.0f)));
  831. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition).Times(0);
  832. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition).Times(0);
  833. UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
  834. }
  835. TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollUnderflow) {
  836. SetDocumentDimensions({100, 200});
  837. EXPECT_CALL(*client_ptr_, GetScrollPosition)
  838. .WillRepeatedly(Return(gfx::PointF(-1.0f, -1.0f)));
  839. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(0));
  840. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(0));
  841. UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
  842. }
  843. TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollOverflow) {
  844. SetDocumentDimensions({100, 200});
  845. EXPECT_CALL(*client_ptr_, GetScrollPosition)
  846. .WillRepeatedly(Return(gfx::PointF(96.0f, 195.0f)));
  847. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(95));
  848. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(194));
  849. UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
  850. }
  851. TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollOverflowZoomed) {
  852. SetDocumentDimensions({100, 200});
  853. SendViewportMessage(/*zoom=*/2.0);
  854. EXPECT_CALL(*client_ptr_, GetScrollPosition)
  855. .WillRepeatedly(Return(gfx::PointF(196.0f, 395.0f)));
  856. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(195));
  857. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(394));
  858. UpdatePluginGeometryWithoutWaiting(1.0f, gfx::Rect(3, 4, 5, 6));
  859. }
  860. TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollScaled) {
  861. SetDocumentDimensions({100, 200});
  862. EXPECT_CALL(*client_ptr_, GetScrollPosition)
  863. .WillRepeatedly(Return(gfx::PointF(4.0f, 6.0f)));
  864. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(4));
  865. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(6));
  866. UpdatePluginGeometryWithoutWaiting(2.0f, gfx::Rect(3, 4, 5, 6));
  867. }
  868. TEST_F(PdfViewWebPluginTest, UpdateGeometryScrollOverflowScaled) {
  869. SetDocumentDimensions({100, 200});
  870. EXPECT_CALL(*client_ptr_, GetScrollPosition)
  871. .WillRepeatedly(Return(gfx::PointF(195.0f, 395.0f)));
  872. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(194));
  873. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(394));
  874. UpdatePluginGeometryWithoutWaiting(2.0f, gfx::Rect(3, 4, 5, 6));
  875. }
  876. TEST_F(PdfViewWebPluginTest, SetCaretPosition) {
  877. SetDocumentDimensions({16, 9});
  878. UpdatePluginGeometryWithoutWaiting(1.0f, {10, 20, 20, 5});
  879. EXPECT_CALL(*engine_ptr_, SetCaretPosition(gfx::Point(2, 3)));
  880. plugin_->SetCaretPosition({4.0f, 3.0f});
  881. }
  882. TEST_F(PdfViewWebPluginTest, SetCaretPositionNegativeOrigin) {
  883. SetDocumentDimensions({16, 9});
  884. UpdatePluginGeometryWithoutWaiting(1.0f, {-10, -20, 20, 5});
  885. EXPECT_CALL(*engine_ptr_, SetCaretPosition(gfx::Point(2, 3)));
  886. plugin_->SetCaretPosition({4.0f, 3.0f});
  887. }
  888. TEST_F(PdfViewWebPluginTest, SetCaretPositionFractional) {
  889. SetDocumentDimensions({16, 9});
  890. UpdatePluginGeometryWithoutWaiting(1.0f, {10, 20, 20, 5});
  891. EXPECT_CALL(*engine_ptr_, SetCaretPosition(gfx::Point(1, 2)));
  892. plugin_->SetCaretPosition({3.9f, 2.9f});
  893. }
  894. TEST_F(PdfViewWebPluginTest, SetCaretPositionScaled) {
  895. SetDocumentDimensions({16, 9});
  896. UpdatePluginGeometryWithoutWaiting(2.0f, {20, 40, 40, 10});
  897. EXPECT_CALL(*engine_ptr_, SetCaretPosition(gfx::Point(4, 6)));
  898. plugin_->SetCaretPosition({4.0f, 3.0f});
  899. }
  900. TEST_F(PdfViewWebPluginTest, PaintEmptySnapshots) {
  901. TestPaintEmptySnapshots(/*device_scale=*/4.0f,
  902. /*window_rect=*/gfx::Rect(10, 10, 20, 20),
  903. /*paint_rect=*/gfx::Rect(5, 5, 15, 15),
  904. /*expected_clipped_rect=*/gfx::Rect(10, 10, 10, 10));
  905. }
  906. TEST_F(PdfViewWebPluginTest, PaintSnapshots) {
  907. TestPaintSnapshots(/*device_scale=*/4.0f,
  908. /*window_rect=*/gfx::Rect(10, 10, 20, 20),
  909. /*paint_rect=*/gfx::Rect(5, 5, 15, 15),
  910. /*expected_clipped_rect=*/gfx::Rect(10, 10, 10, 10));
  911. }
  912. TEST_F(PdfViewWebPluginTest, PaintSnapshotsWithVariousDeviceScales) {
  913. static constexpr PaintParams kPaintWithVariousScalesParams[] = {
  914. {0.4f, gfx::Rect(8, 8, 30, 30), gfx::Rect(10, 10, 30, 30),
  915. gfx::Rect(10, 10, 28, 28)},
  916. {1.0f, gfx::Rect(8, 8, 30, 30), gfx::Rect(10, 10, 30, 30),
  917. gfx::Rect(10, 10, 28, 28)},
  918. {4.0f, gfx::Rect(8, 8, 30, 30), gfx::Rect(10, 10, 30, 30),
  919. gfx::Rect(10, 10, 28, 28)},
  920. };
  921. for (const auto& params : kPaintWithVariousScalesParams) {
  922. TestPaintSnapshots(params.device_scale, params.window_rect,
  923. params.paint_rect, params.expected_clipped_rect);
  924. }
  925. }
  926. TEST_F(PdfViewWebPluginTest, PaintSnapshotsWithVariousRectPositions) {
  927. static constexpr PaintParams kPaintWithVariousPositionsParams[] = {
  928. // The window origin falls outside the `paint_rect` area.
  929. {4.0f, gfx::Rect(10, 10, 20, 20), gfx::Rect(5, 5, 15, 15),
  930. gfx::Rect(10, 10, 10, 10)},
  931. // The window origin falls within the `paint_rect` area.
  932. {4.0f, gfx::Rect(4, 4, 20, 20), gfx::Rect(8, 8, 15, 15),
  933. gfx::Rect(8, 8, 15, 15)},
  934. };
  935. for (const auto& params : kPaintWithVariousPositionsParams) {
  936. TestPaintSnapshots(params.device_scale, params.window_rect,
  937. params.paint_rect, params.expected_clipped_rect);
  938. }
  939. }
  940. TEST_F(PdfViewWebPluginTest, OnPaintWithMultiplePaintRects) {
  941. SetDocumentDimensions({100, 200});
  942. UpdatePluginGeometryWithoutWaiting(/*device_scale=*/1.0f,
  943. gfx::Rect(0, 0, 40, 40));
  944. EXPECT_CALL(*engine_ptr_, Paint)
  945. .WillRepeatedly(
  946. [](const gfx::Rect& rect, SkBitmap& /*image_data*/,
  947. std::vector<gfx::Rect>& ready,
  948. std::vector<gfx::Rect>& /*pending*/) { ready.push_back(rect); });
  949. std::vector<PaintReadyRect> ready;
  950. std::vector<gfx::Rect> pending;
  951. plugin_->OnPaint(
  952. /*paint_rects=*/{gfx::Rect(5, 5, 10, 10), gfx::Rect(20, 20, 10, 10)},
  953. ready, pending);
  954. // Expect three paints: an initial background-clearing paint, and one for each
  955. // requested paint rectangle.
  956. ASSERT_THAT(ready, SizeIs(3));
  957. EXPECT_THAT(pending, IsEmpty());
  958. EXPECT_EQ(gfx::Rect(0, 0, 90, 90), ready[0].rect());
  959. EXPECT_TRUE(ready[0].flush_now());
  960. EXPECT_EQ(gfx::Rect(5, 5, 10, 10), ready[1].rect());
  961. EXPECT_FALSE(ready[1].flush_now());
  962. EXPECT_EQ(gfx::Rect(20, 20, 10, 10), ready[2].rect());
  963. EXPECT_FALSE(ready[2].flush_now());
  964. // All the requested paints should share the same `SkImage`.
  965. EXPECT_NE(&ready[0].image(), &ready[1].image());
  966. EXPECT_EQ(&ready[1].image(), &ready[2].image());
  967. }
  968. TEST_F(PdfViewWebPluginTest, UpdateLayerTransformWithIdentity) {
  969. plugin_->UpdateLayerTransform(1.0f, gfx::Vector2dF());
  970. TestPaintSnapshots(/*device_scale=*/4.0f,
  971. /*window_rect=*/gfx::Rect(10, 10, 20, 20),
  972. /*paint_rect=*/gfx::Rect(10, 10, 20, 20),
  973. /*expected_clipped_rect=*/gfx::Rect(10, 10, 20, 20));
  974. }
  975. TEST_F(PdfViewWebPluginTest, UpdateLayerTransformWithScale) {
  976. plugin_->UpdateLayerTransform(0.5f, gfx::Vector2dF());
  977. TestPaintSnapshots(/*device_scale=*/4.0f,
  978. /*window_rect=*/gfx::Rect(10, 10, 20, 20),
  979. /*paint_rect=*/gfx::Rect(10, 10, 20, 20),
  980. /*expected_clipped_rect=*/gfx::Rect(10, 10, 10, 10));
  981. }
  982. TEST_F(PdfViewWebPluginTest, UpdateLayerTransformWithTranslate) {
  983. plugin_->UpdateLayerTransform(1.0f, gfx::Vector2dF(-1.25, 1.25));
  984. TestPaintSnapshots(/*device_scale=*/4.0f,
  985. /*window_rect=*/gfx::Rect(10, 10, 20, 20),
  986. /*paint_rect=*/gfx::Rect(10, 10, 20, 20),
  987. /*expected_clipped_rect=*/gfx::Rect(10, 15, 15, 15));
  988. }
  989. TEST_F(PdfViewWebPluginTest, UpdateLayerTransformWithScaleAndTranslate) {
  990. plugin_->UpdateLayerTransform(0.5f, gfx::Vector2dF(-1.25, 1.25));
  991. TestPaintSnapshots(/*device_scale=*/4.0f,
  992. /*window_rect=*/gfx::Rect(10, 10, 20, 20),
  993. /*paint_rect=*/gfx::Rect(10, 10, 20, 20),
  994. /*expected_clipped_rect=*/gfx::Rect(10, 15, 5, 10));
  995. }
  996. TEST_F(PdfViewWebPluginTest, HandleViewportMessageBeforeDocumentLoadComplete) {
  997. EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout(DocumentLayout::Options()));
  998. EXPECT_CALL(*client_ptr_, PostMessage).Times(0);
  999. plugin_->OnMessage(ParseMessage(R"({
  1000. "type": "viewport",
  1001. "userInitiated": false,
  1002. "zoom": 1,
  1003. "layoutOptions": {
  1004. "direction": 0,
  1005. "defaultPageOrientation": 0,
  1006. "twoUpViewEnabled": false,
  1007. },
  1008. "xOffset": 0,
  1009. "yOffset": 0,
  1010. "pinchPhase": 0,
  1011. })"));
  1012. }
  1013. TEST_F(PdfViewWebPluginTest, HandleViewportMessageAfterDocumentLoadComplete) {
  1014. plugin_->DocumentLoadComplete();
  1015. EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout(DocumentLayout::Options()));
  1016. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  1017. "type": "loadProgress",
  1018. "progress": 100.0,
  1019. })")));
  1020. plugin_->OnMessage(ParseMessage(R"({
  1021. "type": "viewport",
  1022. "userInitiated": false,
  1023. "zoom": 1,
  1024. "layoutOptions": {
  1025. "direction": 0,
  1026. "defaultPageOrientation": 0,
  1027. "twoUpViewEnabled": false,
  1028. },
  1029. "xOffset": 0,
  1030. "yOffset": 0,
  1031. "pinchPhase": 0,
  1032. })"));
  1033. }
  1034. TEST_F(PdfViewWebPluginTest, HandleViewportMessageSubsequently) {
  1035. plugin_->OnMessage(ParseMessage(R"({
  1036. "type": "viewport",
  1037. "userInitiated": false,
  1038. "zoom": 1,
  1039. "layoutOptions": {
  1040. "direction": 0,
  1041. "defaultPageOrientation": 0,
  1042. "twoUpViewEnabled": false,
  1043. },
  1044. "xOffset": 0,
  1045. "yOffset": 0,
  1046. "pinchPhase": 0,
  1047. })"));
  1048. DocumentLayout::Options two_up_options;
  1049. two_up_options.set_page_spread(DocumentLayout::PageSpread::kTwoUpOdd);
  1050. EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout(two_up_options));
  1051. EXPECT_CALL(*client_ptr_, PostMessage).Times(0);
  1052. plugin_->OnMessage(ParseMessage(R"({
  1053. "type": "viewport",
  1054. "userInitiated": false,
  1055. "zoom": 1,
  1056. "layoutOptions": {
  1057. "direction": 0,
  1058. "defaultPageOrientation": 0,
  1059. "twoUpViewEnabled": true,
  1060. },
  1061. "xOffset": 0,
  1062. "yOffset": 0,
  1063. "pinchPhase": 0,
  1064. })"));
  1065. }
  1066. TEST_F(PdfViewWebPluginTest, HandleViewportMessageScroll) {
  1067. EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout)
  1068. .WillRepeatedly(Return(gfx::Size(16, 9)));
  1069. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(2));
  1070. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(3));
  1071. plugin_->OnMessage(ParseMessage(R"({
  1072. "type": "viewport",
  1073. "userInitiated": false,
  1074. "zoom": 1,
  1075. "layoutOptions": {
  1076. "direction": 2,
  1077. "defaultPageOrientation": 0,
  1078. "twoUpViewEnabled": false,
  1079. },
  1080. "xOffset": 2,
  1081. "yOffset": 3,
  1082. "pinchPhase": 0,
  1083. })"));
  1084. }
  1085. TEST_F(PdfViewWebPluginTest, HandleViewportMessageScrollRightToLeft) {
  1086. EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout)
  1087. .WillRepeatedly(Return(gfx::Size(16, 9)));
  1088. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(2));
  1089. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(3));
  1090. plugin_->OnMessage(ParseMessage(R"({
  1091. "type": "viewport",
  1092. "userInitiated": false,
  1093. "zoom": 1,
  1094. "layoutOptions": {
  1095. "direction": 1,
  1096. "defaultPageOrientation": 0,
  1097. "twoUpViewEnabled": false,
  1098. },
  1099. "xOffset": 2,
  1100. "yOffset": 3,
  1101. "pinchPhase": 0,
  1102. })"));
  1103. }
  1104. TEST_F(PdfViewWebPluginTest, HandleSetBackgroundColorMessage) {
  1105. ASSERT_NE(SK_ColorGREEN, plugin_->GetBackgroundColor());
  1106. base::Value::Dict message;
  1107. message.Set("type", "setBackgroundColor");
  1108. message.Set("color", static_cast<double>(SK_ColorGREEN));
  1109. plugin_->OnMessage(message);
  1110. EXPECT_EQ(SK_ColorGREEN, plugin_->GetBackgroundColor());
  1111. }
  1112. TEST_F(PdfViewWebPluginTest, HandleInputEvent) {
  1113. UpdatePluginGeometryWithoutWaiting(2.0f, {0, 0, 20, 20});
  1114. EXPECT_CALL(*engine_ptr_, HandleInputEvent)
  1115. .WillRepeatedly([](const blink::WebInputEvent& event) {
  1116. if (!blink::WebInputEvent::IsMouseEventType(event.GetType())) {
  1117. ADD_FAILURE() << "Unexpected event type: " << event.GetType();
  1118. return false;
  1119. }
  1120. const auto& mouse_event =
  1121. static_cast<const blink::WebMouseEvent&>(event);
  1122. EXPECT_EQ(blink::WebInputEvent::Type::kMouseDown,
  1123. mouse_event.GetType());
  1124. EXPECT_EQ(gfx::PointF(10.0f, 40.0f), mouse_event.PositionInWidget());
  1125. return true;
  1126. });
  1127. blink::WebMouseEvent mouse_event;
  1128. mouse_event.SetType(blink::WebInputEvent::Type::kMouseDown);
  1129. mouse_event.SetPositionInWidget(10.0f, 20.0f);
  1130. ui::Cursor dummy_cursor;
  1131. EXPECT_EQ(blink::WebInputEventResult::kHandledApplication,
  1132. plugin_->HandleInputEvent(
  1133. blink::WebCoalescedInputEvent(mouse_event, ui::LatencyInfo()),
  1134. &dummy_cursor));
  1135. }
  1136. class PdfViewWebPluginImeTest : public PdfViewWebPluginTest {
  1137. public:
  1138. void TestImeSetCompositionForPlugin(const blink::WebString& text) {
  1139. EXPECT_CALL(*engine_ptr_, HandleInputEvent).Times(0);
  1140. plugin_->ImeSetCompositionForPlugin(text, std::vector<ui::ImeTextSpan>(),
  1141. gfx::Range(),
  1142. /*selection_start=*/0,
  1143. /*selection_end=*/0);
  1144. }
  1145. void TestImeFinishComposingTextForPlugin(
  1146. const blink::WebString& expected_text) {
  1147. InSequence sequence;
  1148. std::u16string expected_text16 = expected_text.Utf16();
  1149. if (expected_text16.size()) {
  1150. for (const auto& c : expected_text16) {
  1151. base::StringPiece16 expected_key(&c, 1);
  1152. EXPECT_CALL(*engine_ptr_,
  1153. HandleInputEvent(IsExpectedImeKeyEvent(expected_key)))
  1154. .WillOnce(Return(true));
  1155. }
  1156. } else {
  1157. EXPECT_CALL(*engine_ptr_, HandleInputEvent).Times(0);
  1158. }
  1159. plugin_->ImeFinishComposingTextForPlugin(false);
  1160. }
  1161. void TestImeCommitTextForPlugin(const blink::WebString& text) {
  1162. InSequence sequence;
  1163. std::u16string expected_text16 = text.Utf16();
  1164. if (expected_text16.size()) {
  1165. for (const auto& c : expected_text16) {
  1166. base::StringPiece16 event(&c, 1);
  1167. EXPECT_CALL(*engine_ptr_,
  1168. HandleInputEvent(IsExpectedImeKeyEvent(event)))
  1169. .WillOnce(Return(true));
  1170. }
  1171. } else {
  1172. EXPECT_CALL(*engine_ptr_, HandleInputEvent).Times(0);
  1173. }
  1174. plugin_->ImeCommitTextForPlugin(text, std::vector<ui::ImeTextSpan>(),
  1175. gfx::Range(),
  1176. /*relative_cursor_pos=*/0);
  1177. }
  1178. };
  1179. TEST_F(PdfViewWebPluginImeTest, ImeSetCompositionAndFinishAscii) {
  1180. const blink::WebString text = blink::WebString::FromASCII("input");
  1181. TestImeSetCompositionForPlugin(text);
  1182. TestImeFinishComposingTextForPlugin(text);
  1183. }
  1184. TEST_F(PdfViewWebPluginImeTest, ImeSetCompositionAndFinishUnicode) {
  1185. const blink::WebString text = blink::WebString::FromUTF16(u"你好");
  1186. TestImeSetCompositionForPlugin(text);
  1187. TestImeFinishComposingTextForPlugin(text);
  1188. // Calling ImeFinishComposingTextForPlugin() again is a no-op.
  1189. TestImeFinishComposingTextForPlugin("");
  1190. }
  1191. TEST_F(PdfViewWebPluginImeTest, ImeSetCompositionAndFinishEmpty) {
  1192. const blink::WebString text;
  1193. TestImeSetCompositionForPlugin(text);
  1194. TestImeFinishComposingTextForPlugin(text);
  1195. }
  1196. TEST_F(PdfViewWebPluginImeTest, ImeCommitTextForPluginAscii) {
  1197. const blink::WebString text = blink::WebString::FromASCII("a b");
  1198. TestImeCommitTextForPlugin(text);
  1199. }
  1200. TEST_F(PdfViewWebPluginImeTest, ImeCommitTextForPluginUnicode) {
  1201. const blink::WebString text = blink::WebString::FromUTF16(u"さようなら");
  1202. TestImeCommitTextForPlugin(text);
  1203. }
  1204. TEST_F(PdfViewWebPluginImeTest, ImeCommitTextForPluginEmpty) {
  1205. const blink::WebString text;
  1206. TestImeCommitTextForPlugin(text);
  1207. }
  1208. TEST_F(PdfViewWebPluginTest, SelectionChanged) {
  1209. plugin_->EnableAccessibility();
  1210. plugin_->DocumentLoadComplete();
  1211. UpdatePluginGeometryWithoutWaiting(1.0f, {300, 56, 20, 5});
  1212. SetDocumentDimensions({16, 9});
  1213. AccessibilityViewportInfo viewport_info;
  1214. EXPECT_CALL(pdf_service_, SelectionChanged(gfx::PointF(-8.0f, -20.0f), 40,
  1215. gfx::PointF(52.0f, 60.0f), 80));
  1216. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityViewportInfo)
  1217. .WillOnce(SaveArg<0>(&viewport_info));
  1218. plugin_->SelectionChanged({-10, -20, 30, 40}, {50, 60, 70, 80});
  1219. EXPECT_EQ(gfx::Point(), viewport_info.scroll);
  1220. pdf_receiver_.FlushForTesting();
  1221. }
  1222. TEST_F(PdfViewWebPluginTest, SelectionChangedNegativeOrigin) {
  1223. plugin_->EnableAccessibility();
  1224. plugin_->DocumentLoadComplete();
  1225. UpdatePluginGeometryWithoutWaiting(1.0f, {-300, -56, 20, 5});
  1226. SetDocumentDimensions({16, 9});
  1227. AccessibilityViewportInfo viewport_info;
  1228. EXPECT_CALL(pdf_service_, SelectionChanged(gfx::PointF(-8.0f, -20.0f), 40,
  1229. gfx::PointF(52.0f, 60.0f), 80));
  1230. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityViewportInfo)
  1231. .WillOnce(SaveArg<0>(&viewport_info));
  1232. plugin_->SelectionChanged({-10, -20, 30, 40}, {50, 60, 70, 80});
  1233. EXPECT_EQ(gfx::Point(), viewport_info.scroll);
  1234. pdf_receiver_.FlushForTesting();
  1235. }
  1236. TEST_F(PdfViewWebPluginTest, SelectionChangedScaled) {
  1237. plugin_->EnableAccessibility();
  1238. plugin_->DocumentLoadComplete();
  1239. UpdatePluginGeometryWithoutWaiting(2.0f, {600, 112, 40, 10});
  1240. SetDocumentDimensions({16, 9});
  1241. AccessibilityViewportInfo viewport_info;
  1242. EXPECT_CALL(pdf_service_, SelectionChanged(gfx::PointF(-8.0f, -20.0f), 40,
  1243. gfx::PointF(52.0f, 60.0f), 80));
  1244. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityViewportInfo)
  1245. .WillOnce(SaveArg<0>(&viewport_info));
  1246. plugin_->SelectionChanged({-20, -40, 60, 80}, {100, 120, 140, 160});
  1247. EXPECT_EQ(gfx::Point(), viewport_info.scroll);
  1248. pdf_receiver_.FlushForTesting();
  1249. }
  1250. TEST_F(PdfViewWebPluginTest, ChangeTextSelection) {
  1251. ASSERT_FALSE(plugin_->HasSelection());
  1252. ASSERT_TRUE(plugin_->SelectionAsText().IsEmpty());
  1253. ASSERT_TRUE(plugin_->SelectionAsMarkup().IsEmpty());
  1254. static constexpr char kSelectedText[] = "1234";
  1255. EXPECT_CALL(*client_ptr_,
  1256. TextSelectionChanged(blink::WebString::FromUTF8(kSelectedText), 0,
  1257. gfx::Range(0, 4)));
  1258. plugin_->SetSelectedText(kSelectedText);
  1259. EXPECT_TRUE(plugin_->HasSelection());
  1260. EXPECT_EQ(kSelectedText, plugin_->SelectionAsText().Utf8());
  1261. EXPECT_EQ(kSelectedText, plugin_->SelectionAsMarkup().Utf8());
  1262. static constexpr char kEmptyText[] = "";
  1263. EXPECT_CALL(*client_ptr_,
  1264. TextSelectionChanged(blink::WebString::FromUTF8(kEmptyText), 0,
  1265. gfx::Range(0, 0)));
  1266. plugin_->SetSelectedText(kEmptyText);
  1267. EXPECT_FALSE(plugin_->HasSelection());
  1268. EXPECT_TRUE(plugin_->SelectionAsText().IsEmpty());
  1269. EXPECT_TRUE(plugin_->SelectionAsMarkup().IsEmpty());
  1270. }
  1271. TEST_F(PdfViewWebPluginTest, FormTextFieldFocusChangeUpdatesTextInputType) {
  1272. ASSERT_EQ(blink::WebTextInputType::kWebTextInputTypeNone,
  1273. plugin_->GetPluginTextInputType());
  1274. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeText);
  1275. plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kText);
  1276. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  1277. plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kNoFocus);
  1278. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeText);
  1279. plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kText);
  1280. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  1281. plugin_->FormFieldFocusChange(PDFEngine::FocusFieldType::kNonText);
  1282. }
  1283. TEST_F(PdfViewWebPluginTest, SearchString) {
  1284. static constexpr char16_t kPattern[] = u"fox";
  1285. static constexpr char16_t kTarget[] =
  1286. u"The quick brown fox jumped over the lazy Fox";
  1287. {
  1288. static constexpr PDFEngine::Client::SearchStringResult kExpectation[] = {
  1289. {16, 3}};
  1290. EXPECT_THAT(
  1291. plugin_->SearchString(kTarget, kPattern, /*case_sensitive=*/true),
  1292. Pointwise(SearchStringResultEq(), kExpectation));
  1293. }
  1294. {
  1295. static constexpr PDFEngine::Client::SearchStringResult kExpectation[] = {
  1296. {16, 3}, {41, 3}};
  1297. EXPECT_THAT(
  1298. plugin_->SearchString(kTarget, kPattern, /*case_sensitive=*/false),
  1299. Pointwise(SearchStringResultEq(), kExpectation));
  1300. }
  1301. }
  1302. TEST_F(PdfViewWebPluginTest, UpdateFocus) {
  1303. MockFunction<void(int checkpoint_num)> checkpoint;
  1304. {
  1305. InSequence sequence;
  1306. // Focus false -> true: Triggers updates.
  1307. EXPECT_CALL(*client_ptr_, UpdateTextInputState);
  1308. EXPECT_CALL(*client_ptr_, UpdateSelectionBounds);
  1309. EXPECT_CALL(checkpoint, Call(1));
  1310. // Focus true -> true: No updates.
  1311. EXPECT_CALL(checkpoint, Call(2));
  1312. // Focus true -> false: Triggers updates. `UpdateTextInputState` is called
  1313. // twice because it also gets called due to
  1314. // `PDFiumEngine::UpdateFocus(false)`.
  1315. EXPECT_CALL(*client_ptr_, UpdateTextInputState).Times(2);
  1316. EXPECT_CALL(*client_ptr_, UpdateSelectionBounds);
  1317. EXPECT_CALL(checkpoint, Call(3));
  1318. // Focus false -> false: No updates.
  1319. EXPECT_CALL(checkpoint, Call(4));
  1320. // Focus false -> true: Triggers updates.
  1321. EXPECT_CALL(*client_ptr_, UpdateTextInputState);
  1322. EXPECT_CALL(*client_ptr_, UpdateSelectionBounds);
  1323. }
  1324. // The focus type does not matter in this test.
  1325. plugin_->UpdateFocus(/*focused=*/true, blink::mojom::FocusType::kNone);
  1326. checkpoint.Call(1);
  1327. plugin_->UpdateFocus(/*focused=*/true, blink::mojom::FocusType::kNone);
  1328. checkpoint.Call(2);
  1329. plugin_->UpdateFocus(/*focused=*/false, blink::mojom::FocusType::kNone);
  1330. checkpoint.Call(3);
  1331. plugin_->UpdateFocus(/*focused=*/false, blink::mojom::FocusType::kNone);
  1332. checkpoint.Call(4);
  1333. plugin_->UpdateFocus(/*focused=*/true, blink::mojom::FocusType::kNone);
  1334. }
  1335. TEST_F(PdfViewWebPluginTest, ShouldDispatchImeEventsToPlugin) {
  1336. ASSERT_TRUE(plugin_->ShouldDispatchImeEventsToPlugin());
  1337. }
  1338. TEST_F(PdfViewWebPluginTest, CaretChange) {
  1339. EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f));
  1340. UpdatePluginGeometry(
  1341. /*device_scale=*/2.0f, /*window_rect=*/gfx::Rect(12, 24, 36, 48));
  1342. plugin_->CaretChanged(gfx::Rect(10, 20, 30, 40));
  1343. EXPECT_EQ(gfx::Rect(28, 20, 30, 40), plugin_->GetPluginCaretBounds());
  1344. }
  1345. TEST_F(PdfViewWebPluginTest, EnteredEditMode) {
  1346. EXPECT_CALL(pdf_service_, SetPluginCanSave(true));
  1347. EXPECT_CALL(*client_ptr_, PostMessage).Times(AnyNumber());
  1348. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  1349. "type": "setIsEditing",
  1350. })")));
  1351. plugin_->EnteredEditMode();
  1352. pdf_receiver_.FlushForTesting();
  1353. }
  1354. TEST_F(PdfViewWebPluginTest, NotifyNumberOfFindResultsChanged) {
  1355. plugin_->StartFind("x", /*case_sensitive=*/false, /*identifier=*/123);
  1356. const std::vector<gfx::Rect> tickmarks = {gfx::Rect(1, 2), gfx::Rect(3, 4)};
  1357. plugin_->UpdateTickMarks(tickmarks);
  1358. EXPECT_CALL(*client_ptr_, ReportFindInPageTickmarks(tickmarks));
  1359. EXPECT_CALL(*client_ptr_, ReportFindInPageMatchCount(123, 5, true));
  1360. plugin_->NotifyNumberOfFindResultsChanged(/*total=*/5, /*final_result=*/true);
  1361. }
  1362. TEST_F(PdfViewWebPluginTest, OnDocumentLoadComplete) {
  1363. base::Value::Dict metadata;
  1364. metadata.Set("fileSize", "0 B");
  1365. metadata.Set("linearized", false);
  1366. metadata.Set("pageSize", "Varies");
  1367. metadata.Set("canSerializeDocument", true);
  1368. base::Value::Dict message;
  1369. message.Set("type", "metadata");
  1370. message.Set("metadataData", std::move(metadata));
  1371. EXPECT_CALL(*client_ptr_, PostMessage);
  1372. EXPECT_CALL(*client_ptr_, PostMessage(Eq(std::ref(message))));
  1373. plugin_->DocumentLoadComplete();
  1374. }
  1375. class PdfViewWebPluginWithDocInfoTest : public PdfViewWebPluginTest {
  1376. protected:
  1377. class TestPDFiumEngineWithDocInfo : public TestPDFiumEngine {
  1378. public:
  1379. explicit TestPDFiumEngineWithDocInfo(PDFEngine::Client* client)
  1380. : TestPDFiumEngine(client) {
  1381. InitializeDocumentAttachments();
  1382. InitializeDocumentMetadata();
  1383. }
  1384. base::Value::List GetBookmarks() override {
  1385. // Create `bookmark1` which navigates to an in-doc position. This bookmark
  1386. // will be in the top-level bookmark list.
  1387. base::Value::Dict bookmark1;
  1388. bookmark1.Set("title", "Bookmark 1");
  1389. bookmark1.Set("page", 2);
  1390. bookmark1.Set("x", 10);
  1391. bookmark1.Set("y", 20);
  1392. bookmark1.Set("zoom", 2.0);
  1393. // Create `bookmark2` which navigates to a web page. This bookmark will be
  1394. // a child of `bookmark1`.
  1395. base::Value::Dict bookmark2;
  1396. bookmark2.Set("title", "Bookmark 2");
  1397. bookmark2.Set("uri", "test.com");
  1398. base::Value::List children_of_bookmark1;
  1399. children_of_bookmark1.Append(std::move(bookmark2));
  1400. bookmark1.Set("children", std::move(children_of_bookmark1));
  1401. // Create the top-level bookmark list.
  1402. base::Value::List bookmarks;
  1403. bookmarks.Append(std::move(bookmark1));
  1404. return bookmarks;
  1405. }
  1406. absl::optional<gfx::Size> GetUniformPageSizePoints() override {
  1407. return gfx::Size(1000, 1200);
  1408. }
  1409. private:
  1410. void InitializeDocumentAttachments() {
  1411. doc_attachment_info_list().resize(3);
  1412. // A regular attachment.
  1413. doc_attachment_info_list()[0].name = u"attachment1.txt";
  1414. doc_attachment_info_list()[0].creation_date = u"D:20170712214438-07'00'";
  1415. doc_attachment_info_list()[0].modified_date = u"D:20160115091400";
  1416. doc_attachment_info_list()[0].is_readable = true;
  1417. doc_attachment_info_list()[0].size_bytes = 13u;
  1418. // An unreadable attachment.
  1419. doc_attachment_info_list()[1].name = u"attachment2.pdf";
  1420. doc_attachment_info_list()[1].is_readable = false;
  1421. // A readable attachment that exceeds download size limit.
  1422. doc_attachment_info_list()[2].name = u"attachment3.mov";
  1423. doc_attachment_info_list()[2].is_readable = true;
  1424. doc_attachment_info_list()[2].size_bytes =
  1425. PdfViewPluginBase::kMaximumSavedFileSize + 1;
  1426. }
  1427. void InitializeDocumentMetadata() {
  1428. metadata().version = PdfVersion::k1_7;
  1429. metadata().size_bytes = 13u;
  1430. metadata().page_count = 13u;
  1431. metadata().linearized = true;
  1432. metadata().has_attachments = true;
  1433. metadata().form_type = FormType::kAcroForm;
  1434. metadata().title = "Title";
  1435. metadata().author = "Author";
  1436. metadata().subject = "Subject";
  1437. metadata().keywords = "Keywords";
  1438. metadata().creator = "Creator";
  1439. metadata().producer = "Producer";
  1440. ASSERT_TRUE(base::Time::FromUTCString("2021-05-04 11:12:13",
  1441. &metadata().creation_date));
  1442. ASSERT_TRUE(base::Time::FromUTCString("2021-06-04 15:16:17",
  1443. &metadata().mod_date));
  1444. }
  1445. };
  1446. static base::Value::Dict CreateExpectedAttachmentsResponse() {
  1447. base::Value::List attachments;
  1448. {
  1449. base::Value::Dict attachment;
  1450. attachment.Set("name", "attachment1.txt");
  1451. attachment.Set("size", 13);
  1452. attachment.Set("readable", true);
  1453. attachments.Append(std::move(attachment));
  1454. }
  1455. {
  1456. base::Value::Dict attachment;
  1457. attachment.Set("name", "attachment2.pdf");
  1458. attachment.Set("size", 0);
  1459. attachment.Set("readable", false);
  1460. attachments.Append(std::move(attachment));
  1461. }
  1462. {
  1463. base::Value::Dict attachment;
  1464. attachment.Set("name", "attachment3.mov");
  1465. attachment.Set("size", -1);
  1466. attachment.Set("readable", true);
  1467. attachments.Append(std::move(attachment));
  1468. }
  1469. base::Value::Dict message;
  1470. message.Set("type", "attachments");
  1471. message.Set("attachmentsData", std::move(attachments));
  1472. return message;
  1473. }
  1474. static base::Value::Dict CreateExpectedBookmarksResponse(
  1475. base::Value::List bookmarks) {
  1476. base::Value::Dict message;
  1477. message.Set("type", "bookmarks");
  1478. message.Set("bookmarksData", std::move(bookmarks));
  1479. return message;
  1480. }
  1481. static base::Value::Dict CreateExpectedMetadataResponse() {
  1482. base::Value::Dict metadata;
  1483. metadata.Set("version", "1.7");
  1484. metadata.Set("fileSize", "13 B");
  1485. metadata.Set("linearized", true);
  1486. metadata.Set("title", "Title");
  1487. metadata.Set("author", "Author");
  1488. metadata.Set("subject", "Subject");
  1489. metadata.Set("keywords", "Keywords");
  1490. metadata.Set("creator", "Creator");
  1491. metadata.Set("producer", "Producer");
  1492. metadata.Set("creationDate", "5/4/21, 4:12:13 AM");
  1493. metadata.Set("modDate", "6/4/21, 8:16:17 AM");
  1494. metadata.Set("pageSize", "13.89 × 16.67 in (portrait)");
  1495. metadata.Set("canSerializeDocument", true);
  1496. base::Value::Dict message;
  1497. message.Set("type", "metadata");
  1498. message.Set("metadataData", std::move(metadata));
  1499. return message;
  1500. }
  1501. void SetUpClient() override {
  1502. EXPECT_CALL(*client_ptr_, CreateEngine).WillOnce([this]() {
  1503. auto engine = std::make_unique<NiceMock<TestPDFiumEngineWithDocInfo>>(
  1504. plugin_.get());
  1505. engine_ptr_ = engine.get();
  1506. return engine;
  1507. });
  1508. }
  1509. };
  1510. TEST_F(PdfViewWebPluginWithDocInfoTest, OnDocumentLoadComplete) {
  1511. const base::Value::Dict expect_attachments =
  1512. CreateExpectedAttachmentsResponse();
  1513. const base::Value::Dict expect_bookmarks =
  1514. CreateExpectedBookmarksResponse(engine_ptr_->GetBookmarks());
  1515. const base::Value::Dict expect_metadata = CreateExpectedMetadataResponse();
  1516. EXPECT_CALL(*client_ptr_, PostMessage);
  1517. EXPECT_CALL(*client_ptr_, PostMessage(Eq(std::ref(expect_attachments))));
  1518. EXPECT_CALL(*client_ptr_, PostMessage(Eq(std::ref(expect_bookmarks))));
  1519. EXPECT_CALL(*client_ptr_, PostMessage(Eq(std::ref(expect_metadata))));
  1520. plugin_->DocumentLoadComplete();
  1521. }
  1522. class PdfViewWebPluginSaveTest : public PdfViewWebPluginTest {
  1523. protected:
  1524. static void AddDataToValue(base::span<const uint8_t> data,
  1525. base::Value& value) {
  1526. value.GetDict().Set("dataToSave", base::Value(data));
  1527. }
  1528. void SetUpClient() override {
  1529. // Ignore non-"saveData" `PdfViewWebPlugin::Client::PostMessage()` calls.
  1530. EXPECT_CALL(*client_ptr_, PostMessage)
  1531. .WillRepeatedly([](const base::Value::Dict& message) {
  1532. EXPECT_NE("saveData", *message.FindString("type"));
  1533. });
  1534. }
  1535. };
  1536. #if BUILDFLAG(ENABLE_INK)
  1537. TEST_F(PdfViewWebPluginSaveTest, AnnotationInNonEditMode) {
  1538. base::Value expected_response = base::test::ParseJson(R"({
  1539. "type": "saveData",
  1540. "token": "annotation-in-non-edit-mode",
  1541. "fileName": "example.pdf",
  1542. "editModeForTesting": false,
  1543. })");
  1544. AddDataToValue(base::make_span(TestPDFiumEngine::kLoadedData),
  1545. expected_response);
  1546. EXPECT_CALL(pdf_service_, SetPluginCanSave(true));
  1547. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  1548. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(expected_response)));
  1549. plugin_->OnMessage(ParseMessage(R"({
  1550. "type": "save",
  1551. "saveRequestType": 0,
  1552. "token": "annotation-in-non-edit-mode",
  1553. })"));
  1554. pdf_receiver_.FlushForTesting();
  1555. }
  1556. TEST_F(PdfViewWebPluginSaveTest, AnnotationInEditMode) {
  1557. plugin_->EnteredEditMode();
  1558. pdf_receiver_.FlushForTesting();
  1559. base::Value expected_response = base::test::ParseJson(R"({
  1560. "type": "saveData",
  1561. "token": "annotation-in-edit-mode",
  1562. "fileName": "example.pdf",
  1563. "editModeForTesting": true,
  1564. })");
  1565. AddDataToValue(base::make_span(TestPDFiumEngine::kSaveData),
  1566. expected_response);
  1567. EXPECT_CALL(pdf_service_, SetPluginCanSave(true));
  1568. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  1569. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(expected_response)));
  1570. plugin_->OnMessage(ParseMessage(R"({
  1571. "type": "save",
  1572. "saveRequestType": 0,
  1573. "token": "annotation-in-edit-mode",
  1574. })"));
  1575. pdf_receiver_.FlushForTesting();
  1576. }
  1577. #endif // BUILDFLAG(ENABLE_INK)
  1578. TEST_F(PdfViewWebPluginSaveTest, OriginalInNonEditMode) {
  1579. {
  1580. InSequence pdf_service_sequence;
  1581. EXPECT_CALL(pdf_service_, SetPluginCanSave(false));
  1582. EXPECT_CALL(
  1583. pdf_service_,
  1584. SaveUrlAs(GURL(kPdfUrl), network::mojom::ReferrerPolicy::kDefault));
  1585. EXPECT_CALL(pdf_service_, SetPluginCanSave(false));
  1586. }
  1587. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  1588. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  1589. "type": "consumeSaveToken",
  1590. "token": "original-in-non-edit-mode",
  1591. })")));
  1592. plugin_->OnMessage(ParseMessage(R"({
  1593. "type": "save",
  1594. "saveRequestType": 1,
  1595. "token": "original-in-non-edit-mode",
  1596. })"));
  1597. pdf_receiver_.FlushForTesting();
  1598. }
  1599. TEST_F(PdfViewWebPluginSaveTest, OriginalInEditMode) {
  1600. plugin_->EnteredEditMode();
  1601. pdf_receiver_.FlushForTesting();
  1602. {
  1603. InSequence pdf_service_sequence;
  1604. EXPECT_CALL(pdf_service_, SetPluginCanSave(false));
  1605. EXPECT_CALL(
  1606. pdf_service_,
  1607. SaveUrlAs(GURL(kPdfUrl), network::mojom::ReferrerPolicy::kDefault));
  1608. EXPECT_CALL(pdf_service_, SetPluginCanSave(true));
  1609. }
  1610. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  1611. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  1612. "type": "consumeSaveToken",
  1613. "token": "original-in-edit-mode",
  1614. })")));
  1615. plugin_->OnMessage(ParseMessage(R"({
  1616. "type": "save",
  1617. "saveRequestType": 1,
  1618. "token": "original-in-edit-mode",
  1619. })"));
  1620. pdf_receiver_.FlushForTesting();
  1621. }
  1622. #if BUILDFLAG(ENABLE_INK)
  1623. TEST_F(PdfViewWebPluginSaveTest, EditedInNonEditMode) {
  1624. base::Value expected_response = base::test::ParseJson(R"({
  1625. "type": "saveData",
  1626. "token": "edited-in-non-edit-mode",
  1627. "fileName": "example.pdf",
  1628. "editModeForTesting": false,
  1629. })");
  1630. AddDataToValue(base::make_span(TestPDFiumEngine::kLoadedData),
  1631. expected_response);
  1632. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  1633. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(expected_response)));
  1634. plugin_->OnMessage(ParseMessage(R"({
  1635. "type": "save",
  1636. "saveRequestType": 2,
  1637. "token": "edited-in-non-edit-mode",
  1638. })"));
  1639. }
  1640. #endif // BUILDFLAG(ENABLE_INK)
  1641. TEST_F(PdfViewWebPluginSaveTest, EditedInEditMode) {
  1642. plugin_->EnteredEditMode();
  1643. base::Value expected_response = base::test::ParseJson(R"({
  1644. "type": "saveData",
  1645. "token": "edited-in-edit-mode",
  1646. "fileName": "example.pdf",
  1647. "editModeForTesting": true,
  1648. })");
  1649. AddDataToValue(base::make_span(TestPDFiumEngine::kSaveData),
  1650. expected_response);
  1651. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  1652. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(expected_response)));
  1653. plugin_->OnMessage(ParseMessage(R"({
  1654. "type": "save",
  1655. "saveRequestType": 2,
  1656. "token": "edited-in-edit-mode",
  1657. })"));
  1658. }
  1659. class PdfViewWebPluginSubmitFormTest
  1660. : public PdfViewWebPluginWithoutInitializeTest {
  1661. protected:
  1662. void SubmitForm(const std::string& url,
  1663. base::StringPiece form_data = "data") {
  1664. EXPECT_TRUE(plugin_->InitializeForTesting());
  1665. EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader).WillOnce([this]() {
  1666. auto associated_loader =
  1667. std::make_unique<NiceMock<MockWebAssociatedURLLoader>>();
  1668. EXPECT_CALL(*associated_loader, LoadAsynchronously)
  1669. .WillOnce([this](const blink::WebURLRequest& request,
  1670. blink::WebAssociatedURLLoaderClient* /*client*/) {
  1671. // TODO(crbug.com/1322928): The `UrlLoader` created by `LoadUrl()`
  1672. // and `SubmitForm()` shouldn't use different ownership semantics.
  1673. // The loader created by `SubmitForm()` is owned by the plugin, and
  1674. // cannot leak past the destruction of the plugin.
  1675. request_.CopyFrom(request);
  1676. });
  1677. return associated_loader;
  1678. });
  1679. plugin_->SubmitForm(url, form_data.data(), form_data.size());
  1680. }
  1681. void SubmitFailingForm(const std::string& url) {
  1682. EXPECT_TRUE(plugin_->InitializeForTesting());
  1683. EXPECT_CALL(*client_ptr_, CreateAssociatedURLLoader).Times(0);
  1684. constexpr base::StringPiece kFormData = "form data";
  1685. plugin_->SubmitForm(url, kFormData.data(), kFormData.size());
  1686. }
  1687. blink::WebURLRequest request_;
  1688. };
  1689. TEST_F(PdfViewWebPluginSubmitFormTest, RequestMethod) {
  1690. SetUpPluginWithUrl("https://www.example.com/path/to/the.pdf");
  1691. SubmitForm(/*url=*/"");
  1692. EXPECT_EQ(request_.HttpMethod().Utf8(), "POST");
  1693. }
  1694. TEST_F(PdfViewWebPluginSubmitFormTest, RequestBody) {
  1695. SetUpPluginWithUrl("https://www.example.com/path/to/the.pdf");
  1696. constexpr base::StringPiece kFormData = "form data";
  1697. SubmitForm(/*url=*/"", kFormData);
  1698. blink::WebHTTPBody::Element element;
  1699. EXPECT_EQ(request_.HttpBody().ElementCount(), 1u);
  1700. ASSERT_TRUE(request_.HttpBody().ElementAt(0, element));
  1701. ASSERT_EQ(element.type, blink::HTTPBodyElementType::kTypeData);
  1702. EXPECT_THAT(element.data.Copy(), testing::ElementsAreArray(kFormData));
  1703. }
  1704. TEST_F(PdfViewWebPluginSubmitFormTest, RelativeUrl) {
  1705. SetUpPluginWithUrl("https://www.example.com/path/to/the.pdf");
  1706. SubmitForm("relative_endpoint");
  1707. EXPECT_EQ(request_.Url().GetString().Utf8(),
  1708. "https://www.example.com/path/to/relative_endpoint");
  1709. }
  1710. TEST_F(PdfViewWebPluginSubmitFormTest, NoRelativeUrl) {
  1711. SetUpPluginWithUrl("https://www.example.com/path/to/the.pdf");
  1712. SubmitForm("");
  1713. EXPECT_EQ(request_.Url().GetString().Utf8(),
  1714. "https://www.example.com/path/to/the.pdf");
  1715. }
  1716. TEST_F(PdfViewWebPluginSubmitFormTest, AbsoluteUrl) {
  1717. SetUpPluginWithUrl("https://a.example.com/path/to/the.pdf");
  1718. SubmitForm("https://b.example.com/relative_endpoint");
  1719. EXPECT_EQ(request_.Url().GetString().Utf8(),
  1720. "https://b.example.com/relative_endpoint");
  1721. }
  1722. TEST_F(PdfViewWebPluginSubmitFormTest, RelativeUrlInvalidDocumentUrl) {
  1723. SetUpPluginWithUrl("https://www.%B%Ad.com/path/to/the.pdf");
  1724. SubmitFailingForm("relative_endpoint");
  1725. }
  1726. TEST_F(PdfViewWebPluginSubmitFormTest, AbsoluteUrlInvalidDocumentUrl) {
  1727. SetUpPluginWithUrl("https://www.%B%Ad.com/path/to/the.pdf");
  1728. SubmitFailingForm("https://wwww.example.com");
  1729. }
  1730. class PdfViewWebPluginPrintTest : public PdfViewWebPluginTest {
  1731. protected:
  1732. void SetUp() override {
  1733. PdfViewWebPluginTest::SetUp();
  1734. // Size must be at least 1 for conversion to `SkMemoryStream`.
  1735. ON_CALL(*engine_ptr_, PrintPages)
  1736. .WillByDefault(Return(std::vector<uint8_t>(1)));
  1737. canvas_.sk_canvas()->SetPrintingMetafile(&metafile_);
  1738. }
  1739. printing::MetafileSkia metafile_;
  1740. };
  1741. TEST_F(PdfViewWebPluginPrintTest, HighQuality) {
  1742. EXPECT_CALL(*engine_ptr_,
  1743. HasPermission(DocumentPermission::kPrintHighQuality))
  1744. .WillRepeatedly(Return(true));
  1745. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
  1746. .WillRepeatedly(Return(true));
  1747. ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
  1748. plugin_->PrintBegin(blink::WebPrintParams()));
  1749. EXPECT_CALL(
  1750. *engine_ptr_,
  1751. PrintPages(ElementsAre(0),
  1752. Field(&blink::WebPrintParams::rasterize_pdf, IsFalse())));
  1753. plugin_->PrintPage(0, canvas_.sk_canvas());
  1754. plugin_->PrintEnd();
  1755. }
  1756. TEST_F(PdfViewWebPluginPrintTest, HighQualityRasterized) {
  1757. EXPECT_CALL(*engine_ptr_,
  1758. HasPermission(DocumentPermission::kPrintHighQuality))
  1759. .WillRepeatedly(Return(true));
  1760. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
  1761. .WillRepeatedly(Return(true));
  1762. blink::WebPrintParams params;
  1763. params.rasterize_pdf = true;
  1764. ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
  1765. plugin_->PrintBegin(params));
  1766. EXPECT_CALL(
  1767. *engine_ptr_,
  1768. PrintPages(ElementsAre(0),
  1769. Field(&blink::WebPrintParams::rasterize_pdf, IsTrue())));
  1770. plugin_->PrintPage(0, canvas_.sk_canvas());
  1771. plugin_->PrintEnd();
  1772. }
  1773. // Regression test for crbug.com/1307219.
  1774. TEST_F(PdfViewWebPluginPrintTest, LowQuality) {
  1775. EXPECT_CALL(*engine_ptr_,
  1776. HasPermission(DocumentPermission::kPrintHighQuality))
  1777. .WillRepeatedly(Return(false));
  1778. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
  1779. .WillRepeatedly(Return(true));
  1780. ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
  1781. plugin_->PrintBegin(blink::WebPrintParams()));
  1782. EXPECT_CALL(
  1783. *engine_ptr_,
  1784. PrintPages(ElementsAre(0),
  1785. Field(&blink::WebPrintParams::rasterize_pdf, IsTrue())));
  1786. plugin_->PrintPage(0, canvas_.sk_canvas());
  1787. plugin_->PrintEnd();
  1788. }
  1789. // Regression test for crbug.com/1307219.
  1790. TEST_F(PdfViewWebPluginPrintTest, LowQualityRasterized) {
  1791. EXPECT_CALL(*engine_ptr_,
  1792. HasPermission(DocumentPermission::kPrintHighQuality))
  1793. .WillRepeatedly(Return(false));
  1794. EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
  1795. .WillRepeatedly(Return(true));
  1796. blink::WebPrintParams params;
  1797. params.rasterize_pdf = true;
  1798. ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
  1799. plugin_->PrintBegin(params));
  1800. EXPECT_CALL(
  1801. *engine_ptr_,
  1802. PrintPages(ElementsAre(0),
  1803. Field(&blink::WebPrintParams::rasterize_pdf, IsTrue())));
  1804. plugin_->PrintPage(0, canvas_.sk_canvas());
  1805. plugin_->PrintEnd();
  1806. }
  1807. TEST_F(PdfViewWebPluginPrintTest, Disabled) {
  1808. EXPECT_EQ(0, plugin_->PrintBegin(blink::WebPrintParams()));
  1809. }
  1810. TEST_F(PdfViewWebPluginPrintTest, DisabledRasterized) {
  1811. blink::WebPrintParams params;
  1812. params.rasterize_pdf = true;
  1813. EXPECT_EQ(0, plugin_->PrintBegin(params));
  1814. }
  1815. class PdfViewWebPluginPrintPreviewTest : public PdfViewWebPluginTest {
  1816. protected:
  1817. void SetUpClient() override {
  1818. EXPECT_CALL(*client_ptr_, GetEmbedderOriginString)
  1819. .WillRepeatedly(Return("chrome://print/"));
  1820. }
  1821. };
  1822. TEST_F(PdfViewWebPluginPrintPreviewTest, HandleResetPrintPreviewModeMessage) {
  1823. EXPECT_CALL(*client_ptr_, CreateEngine)
  1824. .WillOnce([](PDFEngine::Client* client,
  1825. PDFiumFormFiller::ScriptOption script_option) {
  1826. EXPECT_EQ(PDFiumFormFiller::ScriptOption::kNoJavaScript, script_option);
  1827. auto engine = std::make_unique<NiceMock<TestPDFiumEngine>>(client);
  1828. EXPECT_CALL(*engine, ZoomUpdated);
  1829. EXPECT_CALL(*engine, PageOffsetUpdated);
  1830. EXPECT_CALL(*engine, PluginSizeUpdated);
  1831. EXPECT_CALL(*engine, SetGrayscale(false));
  1832. return engine;
  1833. });
  1834. plugin_->OnMessage(ParseMessage(R"({
  1835. "type": "resetPrintPreviewMode",
  1836. "url": "chrome-untrusted://print/0/0/print.pdf",
  1837. "grayscale": false,
  1838. "pageCount": 1,
  1839. })"));
  1840. }
  1841. TEST_F(PdfViewWebPluginPrintPreviewTest,
  1842. HandleResetPrintPreviewModeMessageSetGrayscale) {
  1843. EXPECT_CALL(*client_ptr_, CreateEngine)
  1844. .WillOnce([](PDFEngine::Client* client,
  1845. PDFiumFormFiller::ScriptOption /*script_option*/) {
  1846. auto engine = std::make_unique<NiceMock<TestPDFiumEngine>>(client);
  1847. EXPECT_CALL(*engine, SetGrayscale(true));
  1848. return engine;
  1849. });
  1850. plugin_->OnMessage(ParseMessage(R"({
  1851. "type": "resetPrintPreviewMode",
  1852. "url": "chrome-untrusted://print/0/0/print.pdf",
  1853. "grayscale": true,
  1854. "pageCount": 1,
  1855. })"));
  1856. }
  1857. TEST_F(PdfViewWebPluginPrintPreviewTest, DocumentLoadComplete) {
  1858. plugin_->OnMessage(ParseMessage(R"({
  1859. "type": "resetPrintPreviewMode",
  1860. "url": "chrome-untrusted://print/0/0/print.pdf",
  1861. "grayscale": false,
  1862. "pageCount": 1,
  1863. })"));
  1864. EXPECT_CALL(*client_ptr_, RecordComputedAction("PDF.LoadSuccess"));
  1865. EXPECT_CALL(*client_ptr_, PostMessage);
  1866. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  1867. "type": "formFocusChange",
  1868. "focused": false,
  1869. })")));
  1870. ExpectUpdateTextInputState(blink::WebTextInputType::kWebTextInputTypeNone);
  1871. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  1872. "type": "printPreviewLoaded",
  1873. })")));
  1874. EXPECT_CALL(*accessibility_data_handler_ptr_, SetAccessibilityDocInfo)
  1875. .Times(0);
  1876. EXPECT_CALL(*client_ptr_, DidStopLoading).Times(0);
  1877. EXPECT_CALL(pdf_service_, UpdateContentRestrictions).Times(0);
  1878. plugin_->DocumentLoadComplete();
  1879. EXPECT_EQ(PdfViewPluginBase::DocumentLoadState::kComplete,
  1880. plugin_->document_load_state_for_testing());
  1881. pdf_receiver_.FlushForTesting();
  1882. }
  1883. TEST_F(PdfViewWebPluginPrintPreviewTest,
  1884. DocumentLoadProgressResetByResetPrintPreviewModeMessage) {
  1885. plugin_->DocumentLoadProgress(2, 100);
  1886. plugin_->OnMessage(ParseMessage(R"({
  1887. "type": "resetPrintPreviewMode",
  1888. "url": "chrome-untrusted://print/123/0/print.pdf",
  1889. "grayscale": false,
  1890. "pageCount": 2,
  1891. })"));
  1892. EXPECT_CALL(*client_ptr_, PostMessage(base::test::IsJson(R"({
  1893. "type": "loadProgress",
  1894. "progress": 3.0,
  1895. })")));
  1896. plugin_->DocumentLoadProgress(3, 100);
  1897. }
  1898. TEST_F(PdfViewWebPluginPrintPreviewTest,
  1899. DocumentLoadProgressNotResetByLoadPreviewPageMessage) {
  1900. plugin_->OnMessage(ParseMessage(R"({
  1901. "type": "resetPrintPreviewMode",
  1902. "url": "chrome-untrusted://print/123/0/print.pdf",
  1903. "grayscale": false,
  1904. "pageCount": 2,
  1905. })"));
  1906. plugin_->DocumentLoadProgress(2, 100);
  1907. plugin_->OnMessage(ParseMessage(R"({
  1908. "type": "loadPreviewPage",
  1909. "url": "chrome-untrusted://print/123/1/print.pdf",
  1910. "index": 1,
  1911. })"));
  1912. EXPECT_CALL(*client_ptr_, PostMessage).Times(0);
  1913. plugin_->DocumentLoadProgress(3, 100);
  1914. }
  1915. TEST_F(PdfViewWebPluginPrintPreviewTest,
  1916. HandleViewportMessageScrollRightToLeft) {
  1917. EXPECT_CALL(*engine_ptr_, ApplyDocumentLayout)
  1918. .WillRepeatedly(Return(gfx::Size(16, 9)));
  1919. EXPECT_CALL(*engine_ptr_, ScrolledToXPosition(14));
  1920. EXPECT_CALL(*engine_ptr_, ScrolledToYPosition(3));
  1921. plugin_->OnMessage(ParseMessage(R"({
  1922. "type": "viewport",
  1923. "userInitiated": false,
  1924. "zoom": 1,
  1925. "layoutOptions": {
  1926. "direction": 1,
  1927. "defaultPageOrientation": 0,
  1928. "twoUpViewEnabled": false,
  1929. },
  1930. "xOffset": -2,
  1931. "yOffset": 3,
  1932. "pinchPhase": 0,
  1933. })"));
  1934. }
  1935. } // namespace chrome_pdf