1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef MEDIAPROVIDER_PDF_JNI_PDFCLIENT_DOCUMENT_H_ 18 #define MEDIAPROVIDER_PDF_JNI_PDFCLIENT_DOCUMENT_H_ 19 20 #define APPNAME "PdfViewerPdfClientLayer" 21 22 #include <memory> 23 #include <unordered_map> 24 #include <utility> 25 26 #include "cpp/fpdf_scopers.h" 27 #include "file.h" 28 #include "form_filler.h" 29 #include "fpdf_formfill.h" 30 #include "fpdfview.h" 31 #include "linux_fileops.h" 32 #include "page.h" 33 #include "rect.h" 34 35 namespace pdfClient { 36 37 // Status of an attempt to load a document. See Java's PdfStatus. 38 enum Status { NONE, REQUIRES_PASSWORD, LOADED, PDF_ERROR, FILE_ERROR, NEED_MORE_DATA }; 39 40 // Should be called once before using any other part of pdfClient. 41 void InitLibrary(); 42 43 // One PDF Document, mostly a wrapper around FPDF_Document. Automatically 44 // closes the FPDF_DOCUMENT when it is destroyed. 45 class Document { 46 public: 47 // Load the document from the given reader using the given password. 48 // If the returned status is LOADED, then a new Document is returned which 49 // now has ownership of the given FileReader. 50 // Any other status will not return a new Document and will not take 51 // ownership of the given FileReader or the underlying file. 52 // If the returned status is NEED_MORE_DATA, then the data that is needed 53 // will be indicated by a call to fileReader->RequestBlock. 54 static Status Load(std::unique_ptr<FileReader> fileReader, const char* password, 55 bool closeFdOnFailure, std::unique_ptr<Document>* result, 56 int* requestedHeaderSize = nullptr, int* requestedFooterSize = nullptr); 57 58 // Wrap a FPDF_DOCUMENT in this Document, auto-close when this is destroyed. Document(ScopedFPDFDocument document,bool is_password_protected)59 Document(ScopedFPDFDocument document, bool is_password_protected) 60 : Document(std::move(document), is_password_protected, nullptr, false, false) {} 61 NumPages()62 int NumPages() const { return FPDF_GetPageCount(document_.get()); } 63 GetFormType()64 int GetFormType() const { return FPDF_GetFormType(document_.get()); } 65 66 /* 67 * Method to obtain a Page of the document. 68 * 69 * retain - Some operations will require the page be retained in memory. 70 * This is relevant to form filling where pages must be held by document in 71 * order to receive invalidated rectangles. 72 */ 73 std::shared_ptr<Page> GetPage(int pageNum, bool retain = false); 74 75 // @TODO(b/312222305): This call is only used for analytics, might go away when we 76 // implement quicker loading of linearized PDFs. IsLinearized()77 bool IsLinearized() const { return is_linearized_; } 78 IsPasswordProtected()79 bool IsPasswordProtected() const { return is_password_protected_; } 80 ShouldScaleForPrinting()81 bool ShouldScaleForPrinting() const { return should_scale_for_printing_; } 82 83 // FPDF_DOCUMENT is automatically closed when destroyed. 84 virtual ~Document(); 85 86 // Clone this document without security into the given file descriptor. 87 bool CloneDocumentWithoutSecurity(LinuxFileOps::FDCloser fd); 88 89 // Save this Document to the given file descriptor, presumably opened for 90 // write or append. Return true on success. 91 bool SaveAs(LinuxFileOps::FDCloser fd); 92 93 // Informs the document that the |rect| of the page bitmap has been 94 // invalidated for the given |page|. This takes place following form filling 95 // operations. |Rect| must be in page coordinates. 96 void NotifyInvalidRect(FPDF_PAGE page, Rectangle_i rect); 97 98 // Removes the page from |pages_| and |fpdf_page_index_lookup_|, if retained, 99 // else no-op. 100 void ReleaseRetainedPage(int pageNum); 101 102 private: 103 // Wrap a FPDF_DOCUMENT in this Document, auto-close when this is destroyed. Document(ScopedFPDFDocument document,bool is_password_protected,std::unique_ptr<FileReader> file_reader,bool is_linearized,bool should_scale_for_printing)104 Document(ScopedFPDFDocument document, bool is_password_protected, 105 std::unique_ptr<FileReader> file_reader, bool is_linearized, 106 bool should_scale_for_printing) 107 : file_reader_(std::move(file_reader)), 108 document_(std::move(document)), 109 form_filler_(this, document_.get()), 110 is_password_protected_(is_password_protected), 111 is_linearized_(is_linearized), 112 should_scale_for_printing_(should_scale_for_printing) {} 113 114 // Disable copy constructor because of the cleanup we do in ~Document. 115 Document(const Document&); 116 117 // Returns true if the page is available. Always returns true if the document 118 // is not being loaded progressively. Should always be called before rendering 119 // or accessing the page - see http://b/21314248 120 bool IsPageAvailable(int pageNum) const; 121 122 // Clone the document by simply copying the source file to the dest file. 123 bool CloneRawFile(int source, int dest); 124 125 // Saves the loaded document back to a file (with security removed). 126 bool SaveAsCopyWithoutSecurity(LinuxFileOps::FDCloser dest); 127 128 // If not null, this will also be deleted when this document is destroyed. 129 std::unique_ptr<FileReader> file_reader_; 130 131 // document_, form_filler_ and pages_ must be initialized and torn down 132 // in this order for required resources to be available 133 ScopedFPDFDocument document_; 134 FormFiller form_filler_; 135 std::unordered_map<int, std::shared_ptr<Page>> pages_; 136 137 // Map relating FPDF_PAGE to Page index for lookup. 138 // FPDF_PAGEs are not owned. 139 std::unordered_map<void*, int> fpdf_page_index_lookup_; 140 141 // Whether the PDF is password protected. 142 bool is_password_protected_ = false; 143 144 // Whether the PDF is linearized. 145 bool is_linearized_ = false; 146 147 // Whether this PDF should be scaled for printing. 148 bool should_scale_for_printing_ = false; 149 }; 150 151 } // namespace pdfClient 152 153 #endif // MEDIAPROVIDER_PDF_JNI_PDFCLIENT_DOCUMENT_H_