1 // Copyright (c) 2012 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 5 #ifndef PDF_PDF_ENGINE_H_ 6 #define PDF_PDF_ENGINE_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <string> 12 #include <vector> 13 14 #include "base/containers/span.h" 15 #include "base/optional.h" 16 #include "base/strings/string16.h" 17 #include "base/time/time.h" 18 #include "base/values.h" 19 #include "build/build_config.h" 20 #include "pdf/document_layout.h" 21 #include "ppapi/c/dev/pp_cursor_type_dev.h" 22 #include "ppapi/c/dev/ppp_printing_dev.h" 23 #include "ppapi/c/ppb_input_event.h" 24 #include "ppapi/cpp/completion_callback.h" 25 #include "ppapi/cpp/image_data.h" 26 #include "ppapi/cpp/private/pdf.h" 27 #include "ppapi/cpp/rect.h" 28 #include "ppapi/cpp/size.h" 29 #include "ppapi/cpp/url_loader.h" 30 #include "ppapi/cpp/var_array.h" 31 #include "ui/base/window_open_disposition.h" 32 #include "ui/gfx/geometry/point_f.h" 33 34 #if defined(OS_WIN) 35 #include <windows.h> 36 #endif 37 38 #if defined(OS_WIN) 39 typedef void (*PDFEnsureTypefaceCharactersAccessible)(const LOGFONT* font, 40 const wchar_t* text, 41 size_t text_length); 42 #endif 43 44 struct PP_PdfAccessibilityActionData; 45 struct PP_PdfPrintSettings_Dev; 46 47 namespace gfx { 48 class Rect; 49 class Size; 50 } 51 52 namespace pp { 53 class InputEvent; 54 class VarDictionary; 55 } 56 57 namespace chrome_pdf { 58 59 struct DocumentMetadata; 60 61 // Do one time initialization of the SDK. 62 // If |enable_v8| is false, then the PDFEngine will not be able to run 63 // JavaScript. 64 void InitializeSDK(bool enable_v8); 65 // Tells the SDK that we're shutting down. 66 void ShutdownSDK(); 67 68 // This class encapsulates a PDF rendering engine. 69 class PDFEngine { 70 public: 71 enum DocumentPermission { 72 PERMISSION_COPY, 73 PERMISSION_COPY_ACCESSIBLE, 74 PERMISSION_PRINT_LOW_QUALITY, 75 PERMISSION_PRINT_HIGH_QUALITY, 76 }; 77 78 // Values other then |kCount| are persisted to logs as part of metric 79 // collection, so should not be changed. 80 enum class FormType { 81 kNone = 0, 82 kAcroForm = 1, 83 kXFAFull = 2, 84 kXFAForeground = 3, 85 kCount = 4, 86 }; 87 88 // Maximum number of parameters a nameddest view can contain. 89 static constexpr size_t kMaxViewParams = 4; 90 91 // Named destination in a document. 92 struct NamedDestination { 93 // 0-based page number. 94 unsigned long page; 95 96 // View fit type (see table 8.2 "Destination syntax" on page 582 of PDF 97 // Reference 1.7). Empty string if not present. 98 std::string view; 99 100 // Number of parameters for the view. 101 unsigned long num_params; 102 103 // Parameters for the view. Their meaning depends on the |view| and their 104 // number is defined by |num_params| but is at most |kMaxViewParams|. 105 float params[kMaxViewParams]; 106 }; 107 108 // Features in a document that are relevant to measure. 109 struct DocumentFeatures { 110 // Number of pages in document. 111 size_t page_count = 0; 112 // Whether any files are attached to document (see "File Attachment 113 // Annotations" on page 637 of PDF Reference 1.7). 114 bool has_attachments = false; 115 // Whether the PDF is Tagged (see 10.7 "Tagged PDF" in PDF Reference 1.7). 116 bool is_tagged = false; 117 // What type of form the document contains. 118 FormType form_type = FormType::kNone; 119 }; 120 121 // The interface that's provided to the rendering engine. 122 class Client { 123 public: ~Client()124 virtual ~Client() {} 125 126 // Proposes a document layout to the client. For the proposed layout to 127 // become effective, the client must call PDFEngine::ApplyDocumentLayout() 128 // with the new layout options (although this call can be asynchronous). 129 virtual void ProposeDocumentLayout(const DocumentLayout& layout) = 0; 130 131 // Informs the client that the given rect needs to be repainted. Invalidate(const pp::Rect & rect)132 virtual void Invalidate(const pp::Rect& rect) {} 133 134 // Informs the client to scroll the plugin area by the given offset. DidScroll(const pp::Point & point)135 virtual void DidScroll(const pp::Point& point) {} 136 137 // Scroll the horizontal/vertical scrollbars to a given position. 138 // Values are in screen coordinates, where 0 is the top/left of the document 139 // and a positive value is the distance in pixels from that line. 140 // For ScrollToY, setting |compensate_for_toolbar| will align the position 141 // with the bottom of the toolbar so the given position is always visible. ScrollToX(int x_in_screen_coords)142 virtual void ScrollToX(int x_in_screen_coords) {} ScrollToY(int y_in_screen_coords,bool compensate_for_toolbar)143 virtual void ScrollToY(int y_in_screen_coords, 144 bool compensate_for_toolbar) {} 145 146 // Scroll by a given delta relative to the current position. ScrollBy(const pp::Point & point)147 virtual void ScrollBy(const pp::Point& point) {} 148 149 // Scroll to zero-based |page|. ScrollToPage(int page)150 virtual void ScrollToPage(int page) {} 151 152 // Navigate to the given url. NavigateTo(const std::string & url,WindowOpenDisposition disposition)153 virtual void NavigateTo(const std::string& url, 154 WindowOpenDisposition disposition) {} 155 156 // Navigate to the given destination. Zero-based |page| index. |x|, |y| and 157 // |zoom| are optional and can be nullptr. NavigateToDestination(int page,const float * x,const float * y,const float * zoom)158 virtual void NavigateToDestination(int page, 159 const float* x, 160 const float* y, 161 const float* zoom) {} 162 163 // Updates the cursor. UpdateCursor(PP_CursorType_Dev cursor)164 virtual void UpdateCursor(PP_CursorType_Dev cursor) {} 165 166 // Updates the tick marks in the vertical scrollbar. UpdateTickMarks(const std::vector<pp::Rect> & tickmarks)167 virtual void UpdateTickMarks(const std::vector<pp::Rect>& tickmarks) {} 168 169 // Updates the number of find results for the current search term. If 170 // there are no matches 0 should be passed in. Only when the plugin has 171 // finished searching should it pass in the final count with final_result 172 // set to true. NotifyNumberOfFindResultsChanged(int total,bool final_result)173 virtual void NotifyNumberOfFindResultsChanged(int total, 174 bool final_result) {} 175 176 // Updates the index of the currently selected search item. NotifySelectedFindResultChanged(int current_find_index)177 virtual void NotifySelectedFindResultChanged(int current_find_index) {} 178 179 // Prompts the user for a password to open this document. The callback is 180 // called when the password is retrieved. GetDocumentPassword(pp::CompletionCallbackWithOutput<pp::Var> callback)181 virtual void GetDocumentPassword( 182 pp::CompletionCallbackWithOutput<pp::Var> callback) {} 183 184 // Play a "beeping" sound. Beep()185 virtual void Beep() {} 186 187 // Puts up an alert with the given message. Alert(const std::string & message)188 virtual void Alert(const std::string& message) {} 189 190 // Puts up a confirm with the given message, and returns true if the user 191 // presses OK, or false if they press cancel. 192 virtual bool Confirm(const std::string& message) = 0; 193 194 // Puts up a prompt with the given message and default answer and returns 195 // the answer. 196 virtual std::string Prompt(const std::string& question, 197 const std::string& default_answer) = 0; 198 199 // Returns the url of the pdf. 200 virtual std::string GetURL() = 0; 201 202 // Send an email. Email(const std::string & to,const std::string & cc,const std::string & bcc,const std::string & subject,const std::string & body)203 virtual void Email(const std::string& to, 204 const std::string& cc, 205 const std::string& bcc, 206 const std::string& subject, 207 const std::string& body) {} 208 209 // Put up the print dialog. Print()210 virtual void Print() {} 211 212 // Submit the data using HTTP POST. SubmitForm(const std::string & url,const void * data,int length)213 virtual void SubmitForm(const std::string& url, 214 const void* data, 215 int length) {} 216 217 // Creates and returns new URL loader for partial document requests. 218 virtual pp::URLLoader CreateURLLoader() = 0; 219 220 // Searches the given string for "term" and returns the results. Unicode- 221 // aware. 222 struct SearchStringResult { 223 int start_index; 224 int length; 225 }; 226 virtual std::vector<SearchStringResult> SearchString( 227 const base::char16* string, 228 const base::char16* term, 229 bool case_sensitive) = 0; 230 231 // Notifies the client that the document has finished loading. DocumentLoadComplete(const DocumentFeatures & document_features)232 virtual void DocumentLoadComplete( 233 const DocumentFeatures& document_features) {} 234 235 // Notifies the client that the document has failed to load. DocumentLoadFailed()236 virtual void DocumentLoadFailed() {} 237 238 virtual pp::Instance* GetPluginInstance() = 0; 239 240 // Notifies that an unsupported feature in the PDF was encountered. DocumentHasUnsupportedFeature(const std::string & feature)241 virtual void DocumentHasUnsupportedFeature(const std::string& feature) {} 242 243 // Notifies the client about document load progress. DocumentLoadProgress(uint32_t available,uint32_t doc_size)244 virtual void DocumentLoadProgress(uint32_t available, uint32_t doc_size) {} 245 246 // Notifies the client about focus changes for form text fields. FormTextFieldFocusChange(bool in_focus)247 virtual void FormTextFieldFocusChange(bool in_focus) {} 248 249 // Returns true if the plugin has been opened within print preview. 250 virtual bool IsPrintPreview() = 0; 251 252 // Get the background color of the PDF. 253 virtual uint32_t GetBackgroundColor() = 0; 254 255 // Sets selection status. IsSelectingChanged(bool is_selecting)256 virtual void IsSelectingChanged(bool is_selecting) {} 257 SelectionChanged(const pp::Rect & left,const pp::Rect & right)258 virtual void SelectionChanged(const pp::Rect& left, const pp::Rect& right) { 259 } 260 261 // Sets edit mode state. IsEditModeChanged(bool is_edit_mode)262 virtual void IsEditModeChanged(bool is_edit_mode) {} 263 264 // Gets the height of the top toolbar in screen coordinates. This is 265 // independent of whether it is hidden or not at the moment. 266 virtual float GetToolbarHeightInScreenCoords() = 0; 267 }; 268 269 struct AccessibilityLinkInfo { 270 std::string url; 271 int start_char_index; 272 int char_count; 273 pp::FloatRect bounds; 274 }; 275 276 struct AccessibilityImageInfo { 277 std::string alt_text; 278 pp::FloatRect bounds; 279 }; 280 281 struct AccessibilityHighlightInfo { 282 int start_char_index = -1; 283 int char_count; 284 pp::FloatRect bounds; 285 uint32_t color; 286 }; 287 288 struct AccessibilityTextFieldInfo { 289 AccessibilityTextFieldInfo(); 290 AccessibilityTextFieldInfo(const AccessibilityTextFieldInfo& that); 291 ~AccessibilityTextFieldInfo(); 292 293 std::string name; 294 std::string value; 295 bool is_read_only; 296 bool is_required; 297 bool is_password; 298 pp::FloatRect bounds; 299 }; 300 301 // Factory method to create an instance of the PDF Engine. 302 static std::unique_ptr<PDFEngine> Create(Client* client, 303 bool enable_javascript); 304 ~PDFEngine()305 virtual ~PDFEngine() {} 306 307 // Most of these functions are similar to the Pepper functions of the same 308 // name, so not repeating the description here unless it's different. 309 virtual bool New(const char* url, const char* headers) = 0; 310 virtual void PageOffsetUpdated(const pp::Point& page_offset) = 0; 311 virtual void PluginSizeUpdated(const pp::Size& size) = 0; 312 virtual void ScrolledToXPosition(int position) = 0; 313 virtual void ScrolledToYPosition(int position) = 0; 314 // Paint is called a series of times. Before these n calls are made, PrePaint 315 // is called once. After Paint is called n times, PostPaint is called once. 316 virtual void PrePaint() = 0; 317 virtual void Paint(const pp::Rect& rect, 318 pp::ImageData* image_data, 319 std::vector<pp::Rect>* ready, 320 std::vector<pp::Rect>* pending) = 0; 321 virtual void PostPaint() = 0; 322 virtual bool HandleDocumentLoad(const pp::URLLoader& loader) = 0; 323 virtual bool HandleEvent(const pp::InputEvent& event) = 0; 324 virtual uint32_t QuerySupportedPrintOutputFormats() = 0; 325 virtual void PrintBegin() = 0; 326 virtual pp::Resource PrintPages( 327 const PP_PrintPageNumberRange_Dev* page_ranges, 328 uint32_t page_range_count, 329 const PP_PrintSettings_Dev& print_settings, 330 const PP_PdfPrintSettings_Dev& pdf_print_settings) = 0; 331 virtual void PrintEnd() = 0; 332 virtual void StartFind(const std::string& text, bool case_sensitive) = 0; 333 virtual bool SelectFindResult(bool forward) = 0; 334 virtual void StopFind() = 0; 335 virtual void ZoomUpdated(double new_zoom_level) = 0; 336 virtual void RotateClockwise() = 0; 337 virtual void RotateCounterclockwise() = 0; 338 virtual void SetTwoUpView(bool enable) = 0; 339 340 // Applies the document layout options proposed by a call to 341 // PDFEngine::Client::ProposeDocumentLayout(), returning the overall size of 342 // the new effective layout. 343 virtual pp::Size ApplyDocumentLayout( 344 const DocumentLayout::Options& options) = 0; 345 346 virtual std::string GetSelectedText() = 0; 347 // Returns true if focus is within an editable form text area. 348 virtual bool CanEditText() = 0; 349 // Returns true if focus is within an editable form text area and the text 350 // area has text. 351 virtual bool HasEditableText() = 0; 352 // Replace selected text within an editable form text area with another 353 // string. If there is no selected text, append the replacement text after the 354 // current caret position. 355 virtual void ReplaceSelection(const std::string& text) = 0; 356 // Methods to check if undo/redo is possible, and to perform them. 357 virtual bool CanUndo() = 0; 358 virtual bool CanRedo() = 0; 359 virtual void Undo() = 0; 360 virtual void Redo() = 0; 361 // Handles actions invoked by Accessibility clients. 362 virtual void HandleAccessibilityAction( 363 const PP_PdfAccessibilityActionData& action_data) = 0; 364 virtual std::string GetLinkAtPosition(const pp::Point& point) = 0; 365 // Checks the permissions associated with this document. 366 virtual bool HasPermission(DocumentPermission permission) const = 0; 367 virtual void SelectAll() = 0; 368 // Gets metadata about the document. 369 virtual const DocumentMetadata& GetDocumentMetadata() const = 0; 370 // Gets the number of pages in the document. 371 virtual int GetNumberOfPages() = 0; 372 // Gets the named destination by name. 373 virtual base::Optional<PDFEngine::NamedDestination> GetNamedDestination( 374 const std::string& destination) = 0; 375 // Gets the index of the most visible page, or -1 if none are visible. 376 virtual int GetMostVisiblePage() = 0; 377 // Gets the rectangle of the page not including the shadow. 378 virtual pp::Rect GetPageBoundsRect(int index) = 0; 379 // Gets the rectangle of the page excluding any additional areas. 380 virtual pp::Rect GetPageContentsRect(int index) = 0; 381 // Returns a page's rect in screen coordinates, as well as its surrounding 382 // border areas and bottom separator. 383 virtual pp::Rect GetPageScreenRect(int page_index) const = 0; 384 // Gets the offset of the vertical scrollbar from the top in document 385 // coordinates. 386 virtual int GetVerticalScrollbarYPosition() = 0; 387 // Set color / grayscale rendering modes. 388 virtual void SetGrayscale(bool grayscale) = 0; 389 // Get the number of characters on a given page. 390 virtual int GetCharCount(int page_index) = 0; 391 // Get the bounds in page pixels of a character on a given page. 392 virtual pp::FloatRect GetCharBounds(int page_index, int char_index) = 0; 393 // Get a given unicode character on a given page. 394 virtual uint32_t GetCharUnicode(int page_index, int char_index) = 0; 395 // Given a start char index, find the longest continuous run of text that's 396 // in a single direction and with the same text style. Return a filled out 397 // pp::PDF::PrivateAccessibilityTextRunInfo on success or base::nullopt on 398 // failure. e.g. When |start_char_index| is out of bounds. 399 virtual base::Optional<pp::PDF::PrivateAccessibilityTextRunInfo> 400 GetTextRunInfo(int page_index, int start_char_index) = 0; 401 // For all the links on page |page_index|, get their urls, underlying text 402 // ranges and bounding boxes. 403 virtual std::vector<AccessibilityLinkInfo> GetLinkInfo(int page_index) = 0; 404 // For all the images in page |page_index|, get their alt texts and bounding 405 // boxes. 406 virtual std::vector<AccessibilityImageInfo> GetImageInfo(int page_index) = 0; 407 // For all the highlights in page |page_index|, get their underlying text 408 // ranges and bounding boxes. 409 virtual std::vector<AccessibilityHighlightInfo> GetHighlightInfo( 410 int page_index) = 0; 411 // For all the text fields in page |page_index|, get their properties like 412 // name, value, bounding boxes etc. 413 virtual std::vector<AccessibilityTextFieldInfo> GetTextFieldInfo( 414 int page_index) = 0; 415 416 // Gets the PDF document's print scaling preference. True if the document can 417 // be scaled to fit. 418 virtual bool GetPrintScaling() = 0; 419 // Returns number of copies to be printed. 420 virtual int GetCopiesToPrint() = 0; 421 // Returns the duplex setting. 422 virtual int GetDuplexType() = 0; 423 // Returns true if all the pages are the same size. 424 virtual bool GetPageSizeAndUniformity(pp::Size* size) = 0; 425 426 // Returns a VarArray of Bookmarks, each a VarDictionary containing the 427 // following key/values: 428 // - "title" - a string Var. 429 // - "page" - an int Var. 430 // - "children" - a VarArray(), with each entry containing a VarDictionary of 431 // the same structure. 432 virtual pp::VarArray GetBookmarks() = 0; 433 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; 440 441 virtual std::vector<uint8_t> GetSaveData() = 0; 442 443 virtual void SetCaretPosition(const pp::Point& position) = 0; 444 virtual void MoveRangeSelectionExtent(const pp::Point& extent) = 0; 445 virtual void SetSelectionBounds(const pp::Point& base, 446 const pp::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; 451 452 // Remove focus from form widgets, consolidating the user input. 453 virtual void KillFormFocus() = 0; 454 455 virtual uint32_t GetLoadedByteSize() = 0; 456 virtual bool ReadLoadedBytes(uint32_t length, void* buffer) = 0; 457 }; 458 459 // Interface for exports that wrap the PDF engine. 460 class PDFEngineExports { 461 public: 462 struct RenderingSettings { 463 RenderingSettings(int dpi_x, 464 int dpi_y, 465 const pp::Rect& bounds, 466 bool fit_to_bounds, 467 bool stretch_to_bounds, 468 bool keep_aspect_ratio, 469 bool center_in_bounds, 470 bool autorotate, 471 bool use_color); 472 RenderingSettings(const RenderingSettings& that); 473 474 int dpi_x; 475 int dpi_y; 476 pp::Rect bounds; 477 bool fit_to_bounds; 478 bool stretch_to_bounds; 479 bool keep_aspect_ratio; 480 bool center_in_bounds; 481 bool autorotate; 482 bool use_color; 483 }; 484 PDFEngineExports()485 PDFEngineExports() {} ~PDFEngineExports()486 virtual ~PDFEngineExports() {} 487 488 static PDFEngineExports* Get(); 489 490 #if defined(OS_CHROMEOS) 491 // See the definition of CreateFlattenedPdf in pdf.cc for details. 492 virtual std::vector<uint8_t> CreateFlattenedPdf( 493 base::span<const uint8_t> input_buffer) = 0; 494 #endif // defined(OS_CHROMEOS) 495 496 #if defined(OS_WIN) 497 // See the definition of RenderPDFPageToDC in pdf.cc for details. 498 virtual bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer, 499 int page_number, 500 const RenderingSettings& settings, 501 HDC dc) = 0; 502 503 virtual void SetPDFEnsureTypefaceCharactersAccessible( 504 PDFEnsureTypefaceCharactersAccessible func) = 0; 505 506 virtual void SetPDFUseGDIPrinting(bool enable) = 0; 507 virtual void SetPDFUsePrintMode(int mode) = 0; 508 #endif // defined(OS_WIN) 509 510 // See the definition of RenderPDFPageToBitmap in pdf.cc for details. 511 virtual bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer, 512 int page_number, 513 const RenderingSettings& settings, 514 void* bitmap_buffer) = 0; 515 516 // See the definition of ConvertPdfPagesToNupPdf in pdf.cc for details. 517 virtual std::vector<uint8_t> ConvertPdfPagesToNupPdf( 518 std::vector<base::span<const uint8_t>> input_buffers, 519 size_t pages_per_sheet, 520 const gfx::Size& page_size, 521 const gfx::Rect& printable_area) = 0; 522 523 // See the definition of ConvertPdfDocumentToNupPdf in pdf.cc for details. 524 virtual std::vector<uint8_t> ConvertPdfDocumentToNupPdf( 525 base::span<const uint8_t> input_buffer, 526 size_t pages_per_sheet, 527 const gfx::Size& page_size, 528 const gfx::Rect& printable_area) = 0; 529 530 virtual bool GetPDFDocInfo(base::span<const uint8_t> pdf_buffer, 531 int* page_count, 532 double* max_page_width) = 0; 533 534 // Whether the PDF is Tagged (see 10.7 "Tagged PDF" in PDF Reference 1.7). 535 // Returns true if it's a tagged (accessible) PDF, false if it's a valid 536 // PDF but untagged, and nullopt if the PDF can't be parsed. 537 virtual base::Optional<bool> IsPDFDocTagged( 538 base::span<const uint8_t> pdf_buffer) = 0; 539 540 // Given a tagged PDF (see IsPDFDocTagged, above), return the portion of 541 // the structure tree for a given page as a hierarchical tree of base::Values. 542 virtual base::Value GetPDFStructTreeForPage( 543 base::span<const uint8_t> pdf_buffer, 544 int page_index) = 0; 545 546 // See the definition of GetPDFPageSizeByIndex in pdf.cc for details. 547 virtual bool GetPDFPageSizeByIndex(base::span<const uint8_t> pdf_buffer, 548 int page_number, 549 double* width, 550 double* height) = 0; 551 }; 552 553 } // namespace chrome_pdf 554 555 #endif // PDF_PDF_ENGINE_H_ 556