1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef PDF_PDF_ENGINE_H_
6 #define PDF_PDF_ENGINE_H_
14 #include "base/callback.h"
15 #include "base/containers/span.h"
16 #include "base/time/time.h"
17 #include "base/values.h"
18 #include "build/build_config.h"
19 #include "pdf/document_layout.h"
20 #include "printing/mojom/print.mojom-forward.h"
21 #include "third_party/abseil-cpp/absl/types/optional.h"
22 #include "third_party/skia/include/core/SkColor.h"
23 #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h"
24 #include "ui/base/window_open_disposition.h"
25 #include "ui/gfx/geometry/point_f.h"
26 #include "ui/gfx/geometry/rect.h"
27 #include "ui/gfx/geometry/rect_f.h"
37 struct WebPrintParams;
48 namespace chrome_pdf {
52 struct AccessibilityActionData;
53 struct AccessibilityFocusInfo;
54 struct AccessibilityLinkInfo;
55 struct AccessibilityHighlightInfo;
56 struct AccessibilityImageInfo;
57 struct AccessibilityTextFieldInfo;
58 struct AccessibilityTextRunInfo;
59 struct DocumentAttachmentInfo;
60 struct DocumentMetadata;
62 using SendThumbnailCallback = base::OnceCallback<void(Thumbnail)>;
64 enum class FontMappingMode {
65 // Do not perform font mapping.
67 // Perform font mapping in renderer processes using Blink/content APIs.
71 enum class DocumentPermission {
78 // Do one time initialization of the SDK.
79 // If `enable_v8` is false, then the PDFEngine will not be able to run
81 void InitializeSDK(bool enable_v8, FontMappingMode font_mapping_mode);
82 // Tells the SDK that we're shutting down.
85 // This class encapsulates a PDF rendering engine.
88 // Maximum number of parameters a nameddest view can contain.
89 static constexpr size_t kMaxViewParams = 4;
91 enum class FocusFieldType {
92 // Focus is not on any form field.
94 // Focus is on a form text field or form combobox text field.
96 // Focus is on a non-text field.
100 // Named destination in a document.
101 struct NamedDestination {
102 // 0-based page number.
105 // View fit type (see table 8.2 "Destination syntax" on page 582 of PDF
106 // Reference 1.7). Empty string if not present.
109 // Number of parameters for the view.
110 unsigned long num_params;
112 // Parameters for the view. Their meaning depends on the `view` and their
113 // number is defined by `num_params` but is at most `kMaxViewParams`. Note:
114 // If a parameter stands for the x/y coordinates, it should be transformed
115 // into the corresponding in-screen coordinates before it's sent to the
117 float params[kMaxViewParams];
119 // A string of parameters for view fit type XYZ in the format of "x,y,zoom",
120 // where x and y parameters are the in-screen coordinates and zoom is the
121 // zoom level. If a parameter is "null", then current value of that
122 // parameter in the viewport should be retained. Note: This string is empty
123 // if the view's fit type is not XYZ.
124 std::string xyz_params;
127 // The interface that's provided to the rendering engine.
130 virtual ~Client() = default;
132 // Proposes a document layout to the client. For the proposed layout to
133 // become effective, the client must call PDFEngine::ApplyDocumentLayout()
134 // with the new layout options (although this call can be asynchronous).
135 virtual void ProposeDocumentLayout(const DocumentLayout& layout) = 0;
137 // Informs the client that the given rect needs to be repainted.
138 virtual void Invalidate(const gfx::Rect& rect) {}
140 // Informs the client to scroll the plugin area by the given offset.
141 virtual void DidScroll(const gfx::Vector2d& offset) {}
143 // Scroll the horizontal/vertical scrollbars to a given position.
144 // Values are in screen coordinates, where 0 is the top/left of the document
145 // and a positive value is the distance in pixels from that line.
146 virtual void ScrollToX(int x_screen_coords) {}
147 virtual void ScrollToY(int y_screen_coords) {}
149 // Scroll by a given delta relative to the current position.
150 virtual void ScrollBy(const gfx::Vector2d& delta) {}
152 // Scroll to zero-based `page`.
153 virtual void ScrollToPage(int page) {}
155 // Navigate to the given url.
156 virtual void NavigateTo(const std::string& url,
157 WindowOpenDisposition disposition) {}
159 // Navigate to the given destination. Zero-based `page` index. `x`, `y` and
160 // `zoom` are optional and can be nullptr.
161 virtual void NavigateToDestination(int page,
164 const float* zoom) {}
166 // Updates the cursor.
167 virtual void UpdateCursor(ui::mojom::CursorType new_cursor_type) {}
169 // Updates the tick marks in the vertical scrollbar.
170 virtual void UpdateTickMarks(const std::vector<gfx::Rect>& tickmarks) {}
172 // Updates the number of find results for the current search term. If
173 // there are no matches 0 should be passed in. Only when the plugin has
174 // finished searching should it pass in the final count with `final_result`
176 virtual void NotifyNumberOfFindResultsChanged(int total,
177 bool final_result) {}
179 // Updates the index of the currently selected search item. Set
180 // `final_result` to true only when there is no subsequent
181 // `NotifyNumberOfFindResultsChanged()` call.
182 virtual void NotifySelectedFindResultChanged(int current_find_index,
183 bool final_result) {}
185 virtual void NotifyTouchSelectionOccurred() {}
187 // Prompts the user for a password to open this document. The callback is
188 // called when the password is retrieved.
189 virtual void GetDocumentPassword(
190 base::OnceCallback<void(const std::string&)> callback) {}
192 // Play a "beeping" sound.
193 virtual void Beep() {}
195 // Puts up an alert with the given message.
196 virtual void Alert(const std::string& message) {}
198 // Puts up a confirm with the given message, and returns true if the user
199 // presses OK, or false if they press cancel.
200 virtual bool Confirm(const std::string& message) = 0;
202 // Puts up a prompt with the given message and default answer and returns
204 virtual std::string Prompt(const std::string& question,
205 const std::string& default_answer) = 0;
207 // Returns the url of the pdf.
208 virtual std::string GetURL() = 0;
211 virtual void Email(const std::string& to,
212 const std::string& cc,
213 const std::string& bcc,
214 const std::string& subject,
215 const std::string& body) {}
217 // Put up the print dialog.
218 virtual void Print() {}
220 // Submit the data using HTTP POST.
221 virtual void SubmitForm(const std::string& url,
225 // Creates and returns new URL loader for partial document requests.
226 virtual std::unique_ptr<UrlLoader> CreateUrlLoader() = 0;
228 // Searches the given string for "term" and returns the results. Unicode-
230 struct SearchStringResult {
234 virtual std::vector<SearchStringResult> SearchString(
235 const char16_t* string,
236 const char16_t* term,
237 bool case_sensitive) = 0;
239 // Notifies the client that the document has finished loading.
240 virtual void DocumentLoadComplete() {}
242 // Notifies the client that the document has failed to load.
243 virtual void DocumentLoadFailed() {}
245 // Notifies that an unsupported feature in the PDF was encountered.
246 virtual void DocumentHasUnsupportedFeature(const std::string& feature) {}
248 // Notifies the client about document load progress.
249 virtual void DocumentLoadProgress(uint32_t available, uint32_t doc_size) {}
251 // Notifies the client about focus changes for form fields.
252 virtual void FormFieldFocusChange(FocusFieldType type) {}
254 // Returns true if the plugin has been opened within print preview.
255 virtual bool IsPrintPreview() const = 0;
257 // Get the background color of the PDF.
258 virtual SkColor GetBackgroundColor() const = 0;
260 // Sets selection status.
261 virtual void SetIsSelecting(bool is_selecting) {}
263 virtual void SelectionChanged(const gfx::Rect& left,
264 const gfx::Rect& right) {}
266 // The caret position in the editable form (if applicable) changed.
267 virtual void CaretChanged(const gfx::Rect& caret_rect) {}
269 // Notifies the client that the PDF has been edited.
270 virtual void EnteredEditMode() {}
272 // Notifies the client about focus changes for the document.
273 virtual void DocumentFocusChanged(bool document_has_focus) {}
275 // Sets selected text.
276 virtual void SetSelectedText(const std::string& selected_text) = 0;
278 // Sets the link under cursor.
279 virtual void SetLinkUnderCursor(const std::string& link_under_cursor) = 0;
281 // If the link cannot be converted to JS payload struct, then it is not
282 // possible to pass it to JS. In this case, ignore the link like other PDF
284 // See https://crbug.com/312882 for an example.
285 virtual bool IsValidLink(const std::string& url) = 0;
288 virtual ~PDFEngine() = default;
290 // Most of these functions are similar to the Pepper functions of the same
291 // name, so not repeating the description here unless it's different.
292 virtual void PageOffsetUpdated(const gfx::Vector2d& page_offset) = 0;
293 virtual void PluginSizeUpdated(const gfx::Size& size) = 0;
294 virtual void ScrolledToXPosition(int position) = 0;
295 virtual void ScrolledToYPosition(int position) = 0;
296 // Paint is called a series of times. Before these n calls are made, PrePaint
297 // is called once. After Paint is called n times, PostPaint is called once.
298 virtual void PrePaint() = 0;
299 virtual void Paint(const gfx::Rect& rect,
300 SkBitmap& image_data,
301 std::vector<gfx::Rect>& ready,
302 std::vector<gfx::Rect>& pending) = 0;
303 virtual void PostPaint() = 0;
304 virtual bool HandleInputEvent(const blink::WebInputEvent& event) = 0;
305 virtual void PrintBegin() = 0;
306 virtual std::vector<uint8_t> PrintPages(
307 const std::vector<int>& page_index,
308 const blink::WebPrintParams& print_params) = 0;
309 virtual void PrintEnd() = 0;
310 virtual void StartFind(const std::string& text, bool case_sensitive) = 0;
311 virtual bool SelectFindResult(bool forward) = 0;
312 virtual void StopFind() = 0;
313 virtual void ZoomUpdated(double new_zoom_level) = 0;
314 virtual void RotateClockwise() = 0;
315 virtual void RotateCounterclockwise() = 0;
316 virtual bool IsReadOnly() const = 0;
317 virtual void SetReadOnly(bool enable) = 0;
318 virtual void SetDocumentLayout(DocumentLayout::PageSpread page_spread) = 0;
319 virtual void DisplayAnnotations(bool display) = 0;
321 // Applies the document layout options proposed by a call to
322 // PDFEngine::Client::ProposeDocumentLayout(), returning the overall size of
323 // the new effective layout.
324 virtual gfx::Size ApplyDocumentLayout(
325 const DocumentLayout::Options& options) = 0;
327 virtual std::string GetSelectedText() = 0;
328 // Returns true if focus is within an editable form text area.
329 virtual bool CanEditText() const = 0;
330 // Returns true if focus is within an editable form text area and the text
332 virtual bool HasEditableText() const = 0;
333 // Replace selected text within an editable form text area with another
334 // string. If there is no selected text, append the replacement text after the
335 // current caret position.
336 virtual void ReplaceSelection(const std::string& text) = 0;
337 // Methods to check if undo/redo is possible, and to perform them.
338 virtual bool CanUndo() const = 0;
339 virtual bool CanRedo() const = 0;
340 virtual void Undo() = 0;
341 virtual void Redo() = 0;
342 // Handles actions invoked by Accessibility clients.
343 virtual void HandleAccessibilityAction(
344 const AccessibilityActionData& action_data) = 0;
345 virtual std::string GetLinkAtPosition(const gfx::Point& point) = 0;
346 // Checks the permissions associated with this document.
347 virtual bool HasPermission(DocumentPermission permission) const = 0;
348 virtual void SelectAll() = 0;
349 // Gets the list of DocumentAttachmentInfo from the document.
350 virtual const std::vector<DocumentAttachmentInfo>&
351 GetDocumentAttachmentInfoList() const = 0;
352 // Gets the content of an attachment by the attachment's `index`. `index`
353 // must be in the range of [0, attachment_count-1), where `attachment_count`
354 // is the number of attachments embedded in the document.
355 // The caller of this method is responsible for checking whether the
356 // attachment is readable, attachment size is not 0 byte, and the return
357 // value's size matches the corresponding DocumentAttachmentInfo's
359 virtual std::vector<uint8_t> GetAttachmentData(size_t index) = 0;
360 // Gets metadata about the document.
361 virtual const DocumentMetadata& GetDocumentMetadata() const = 0;
362 // Gets the number of pages in the document.
363 virtual int GetNumberOfPages() const = 0;
364 // Gets the named destination by name.
365 virtual absl::optional<PDFEngine::NamedDestination> GetNamedDestination(
366 const std::string& destination) = 0;
367 // Gets the index of the most visible page, or -1 if none are visible.
368 virtual int GetMostVisiblePage() = 0;
369 // Gets the rectangle of the page not including the shadow.
370 virtual gfx::Rect GetPageBoundsRect(int index) = 0;
371 // Gets the rectangle of the page excluding any additional areas.
372 virtual gfx::Rect GetPageContentsRect(int index) = 0;
373 // Returns a page's rect in screen coordinates, as well as its surrounding
374 // border areas and bottom separator.
375 virtual gfx::Rect GetPageScreenRect(int page_index) const = 0;
376 // Set color / grayscale rendering modes.
377 virtual void SetGrayscale(bool grayscale) = 0;
378 // Get the number of characters on a given page.
379 virtual int GetCharCount(int page_index) = 0;
380 // Get the bounds in page pixels of a character on a given page.
381 virtual gfx::RectF GetCharBounds(int page_index, int char_index) = 0;
382 // Get a given unicode character on a given page.
383 virtual uint32_t GetCharUnicode(int page_index, int char_index) = 0;
384 // Given a start char index, find the longest continuous run of text that's
385 // in a single direction and with the same text style. Return a filled out
386 // AccessibilityTextRunInfo on success or absl::nullopt on failure. e.g. When
387 // `start_char_index` is out of bounds.
388 virtual absl::optional<AccessibilityTextRunInfo> GetTextRunInfo(
390 int start_char_index) = 0;
391 // For all the links on page `page_index`, get their urls, underlying text
392 // ranges and bounding boxes.
393 virtual std::vector<AccessibilityLinkInfo> GetLinkInfo(
395 const std::vector<AccessibilityTextRunInfo>& text_runs) = 0;
396 // For all the images in page `page_index`, get their alt texts and bounding
397 // boxes. If the alt text is empty or unavailable, and if the user has
398 // requested that the OCR service tag the PDF so that it is made accessible,
399 // transfer the raw image pixels in the `image_data` field. Otherwise do not
400 // populate the `image_data` field.
401 virtual std::vector<AccessibilityImageInfo> GetImageInfo(
403 uint32_t text_run_count) = 0;
404 // For all the highlights in page `page_index`, get their underlying text
405 // ranges and bounding boxes.
406 virtual std::vector<AccessibilityHighlightInfo> GetHighlightInfo(
408 const std::vector<AccessibilityTextRunInfo>& text_runs) = 0;
409 // For all the text fields in page `page_index`, get their properties like
410 // name, value, bounding boxes etc.
411 virtual std::vector<AccessibilityTextFieldInfo> GetTextFieldInfo(
413 uint32_t text_run_count) = 0;
415 // Gets the PDF document's print scaling preference. True if the document can
417 virtual bool GetPrintScaling() = 0;
418 // Returns number of copies to be printed.
419 virtual int GetCopiesToPrint() = 0;
420 // Returns the duplex setting.
421 virtual printing::mojom::DuplexMode GetDuplexMode() = 0;
422 // Returns the uniform page size of the document in points. Returns
423 // `absl::nullopt` if the document has more than one page size.
424 virtual absl::optional<gfx::Size> GetUniformPageSizePoints() = 0;
426 // Returns a list of Values of Bookmarks. Each Bookmark is a dictionary Value
427 // which contains the following key/values:
428 // - "title" - a string Value.
429 // - "page" - an int Value.
430 // - "children" - a list of Values, with each entry containing
431 // a dictionary Value of the same structure.
432 virtual base::Value::List GetBookmarks() = 0;
434 // Append blank pages to make a 1-page document to a `num_pages` document.
435 // Always retain the first page data.
436 virtual void AppendBlankPages(size_t num_pages) = 0;
437 // Append the first page of the document loaded with the `engine` to this
438 // document at page `index`.
439 virtual void AppendPage(PDFEngine* engine, int index) = 0;
441 virtual std::vector<uint8_t> GetSaveData() = 0;
443 virtual void SetCaretPosition(const gfx::Point& position) = 0;
444 virtual void MoveRangeSelectionExtent(const gfx::Point& extent) = 0;
445 virtual void SetSelectionBounds(const gfx::Point& base,
446 const gfx::Point& extent) = 0;
447 virtual void GetSelection(uint32_t* selection_start_page_index,
448 uint32_t* selection_start_char_index,
449 uint32_t* selection_end_page_index,
450 uint32_t* selection_end_char_index) = 0;
452 // Remove focus from form widgets, consolidating the user input.
453 virtual void KillFormFocus() = 0;
455 // Notify whether the PDF currently has the focus or not.
456 virtual void UpdateFocus(bool has_focus) = 0;
458 // Returns the focus info of current focus item.
459 virtual AccessibilityFocusInfo GetFocusInfo() = 0;
461 virtual uint32_t GetLoadedByteSize() = 0;
462 virtual bool ReadLoadedBytes(uint32_t length, void* buffer) = 0;
464 // Requests for a thumbnail to be sent using a callback when the page is ready
465 // to be rendered. `send_callback` is run with the thumbnail data when ready.
466 virtual void RequestThumbnail(int page_index,
467 float device_pixel_ratio,
468 SendThumbnailCallback send_callback) = 0;
471 // Interface for exports that wrap the PDF engine.
472 class PDFEngineExports {
474 struct RenderingSettings {
475 RenderingSettings(const gfx::Size& dpi,
476 const gfx::Rect& bounds,
478 bool stretch_to_bounds,
479 bool keep_aspect_ratio,
480 bool center_in_bounds,
483 bool render_for_printing);
484 RenderingSettings(const RenderingSettings& that);
489 bool stretch_to_bounds;
490 bool keep_aspect_ratio;
491 bool center_in_bounds;
494 bool render_for_printing;
497 PDFEngineExports() {}
498 virtual ~PDFEngineExports() {}
500 static PDFEngineExports* Get();
502 #if BUILDFLAG(IS_CHROMEOS)
503 // See the definition of CreateFlattenedPdf in pdf.cc for details.
504 virtual std::vector<uint8_t> CreateFlattenedPdf(
505 base::span<const uint8_t> input_buffer) = 0;
506 #endif // BUILDFLAG(IS_CHROMEOS)
508 #if BUILDFLAG(IS_WIN)
509 // See the definition of RenderPDFPageToDC in pdf.cc for details.
510 virtual bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer,
512 const RenderingSettings& settings,
515 virtual void SetPDFUsePrintMode(int mode) = 0;
516 #endif // BUILDFLAG(IS_WIN)
518 // See the definition of RenderPDFPageToBitmap in pdf.cc for details.
519 virtual bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer,
521 const RenderingSettings& settings,
522 void* bitmap_buffer) = 0;
524 // See the definition of ConvertPdfPagesToNupPdf in pdf.cc for details.
525 virtual std::vector<uint8_t> ConvertPdfPagesToNupPdf(
526 std::vector<base::span<const uint8_t>> input_buffers,
527 size_t pages_per_sheet,
528 const gfx::Size& page_size,
529 const gfx::Rect& printable_area) = 0;
531 // See the definition of ConvertPdfDocumentToNupPdf in pdf.cc for details.
532 virtual std::vector<uint8_t> ConvertPdfDocumentToNupPdf(
533 base::span<const uint8_t> input_buffer,
534 size_t pages_per_sheet,
535 const gfx::Size& page_size,
536 const gfx::Rect& printable_area) = 0;
538 virtual bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer,
540 float* max_page_width) = 0;
542 // Whether the PDF is Tagged (see 10.7 "Tagged PDF" in PDF Reference 1.7).
543 // Returns true if it's a tagged (accessible) PDF, false if it's a valid
544 // PDF but untagged, and nullopt if the PDF can't be parsed.
545 virtual absl::optional<bool> IsPDFDocTagged(
546 base::span<const uint8_t> pdf_buffer) = 0;
548 // Given a tagged PDF (see IsPDFDocTagged, above), return the portion of
549 // the structure tree for a given page as a hierarchical tree of base::Values.
550 virtual base::Value GetPDFStructTreeForPage(
551 base::span<const uint8_t> pdf_buffer,
554 // See the definition of GetPDFPageSizeByIndex in pdf.cc for details.
555 virtual absl::optional<gfx::SizeF> GetPDFPageSizeByIndex(
556 base::span<const uint8_t> pdf_buffer,
560 } // namespace chrome_pdf
562 #endif // PDF_PDF_ENGINE_H_