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 CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_PRINT_PREVIEW_UI_H_ 6 #define CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_PRINT_PREVIEW_UI_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <string> 12 #include <vector> 13 14 #include "base/callback_forward.h" 15 #include "base/gtest_prod_util.h" 16 #include "base/macros.h" 17 #include "base/memory/read_only_shared_memory_region.h" 18 #include "base/memory/ref_counted.h" 19 #include "base/optional.h" 20 #include "base/time/time.h" 21 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" 22 #include "components/printing/common/print.mojom.h" 23 #include "mojo/public/cpp/bindings/associated_receiver.h" 24 #include "printing/mojom/print.mojom-forward.h" 25 #include "ui/gfx/geometry/rect.h" 26 #include "ui/gfx/geometry/size.h" 27 28 struct PrintHostMsg_RequestPrintPreview_Params; 29 30 namespace base { 31 class DictionaryValue; 32 class FilePath; 33 class RefCountedMemory; 34 } 35 36 namespace gfx { 37 class Rect; 38 } 39 40 namespace printing { 41 42 class PrintPreviewHandler; 43 44 class PrintPreviewUI : public ConstrainedWebDialogUI, 45 public mojom::PrintPreviewUI { 46 public: 47 explicit PrintPreviewUI(content::WebUI* web_ui); 48 49 ~PrintPreviewUI() override; 50 51 mojo::PendingAssociatedRemote<mojom::PrintPreviewUI> BindPrintPreviewUI(); 52 53 // Gets the print preview |data|. |index| is zero-based, and can be 54 // |COMPLETE_PREVIEW_DOCUMENT_INDEX| to get the entire preview document. 55 virtual void GetPrintPreviewDataForIndex( 56 int index, 57 scoped_refptr<base::RefCountedMemory>* data) const; 58 59 // printing::mojo::PrintPreviewUI: 60 void SetOptionsFromDocument(const mojom::OptionsFromDocumentParamsPtr params, 61 int32_t request_id) override; 62 void PrintPreviewFailed(int32_t document_cookie, int32_t request_id) override; 63 void PrintPreviewCancelled(int32_t document_cookie, 64 int32_t request_id) override; 65 void PrinterSettingsInvalid(int32_t document_cookie, 66 int32_t request_id) override; 67 68 bool IsBound() const; 69 70 // Setters 71 void SetInitiatorTitle(const base::string16& initiator_title); 72 initiator_title()73 const base::string16& initiator_title() const { return initiator_title_; } 74 source_is_arc()75 bool source_is_arc() const { return source_is_arc_; } 76 source_is_modifiable()77 bool source_is_modifiable() const { return source_is_modifiable_; } 78 source_is_pdf()79 bool source_is_pdf() const { return source_is_pdf_; } 80 source_has_selection()81 bool source_has_selection() const { return source_has_selection_; } 82 print_selection_only()83 bool print_selection_only() const { return print_selection_only_; } 84 pages_per_sheet()85 int pages_per_sheet() const { return pages_per_sheet_; } 86 printable_area()87 const gfx::Rect& printable_area() const { return printable_area_; } 88 page_size()89 const gfx::Size& page_size() const { return page_size_; } 90 91 // Returns true if |page_number| is the last page in |pages_to_render_|. 92 // |page_number| is a 0-based number. 93 bool LastPageComposited(uint32_t page_number) const; 94 95 // Get the 0-based index of the |page_number| in |pages_to_render_|. 96 // Same as above, |page_number| is a 0-based number. 97 uint32_t GetPageToNupConvertIndex(uint32_t page_number) const; 98 99 std::vector<base::ReadOnlySharedMemoryRegion> TakePagesForNupConvert(); 100 101 // Save pdf pages temporarily before ready to do N-up conversion. 102 void AddPdfPageForNupConversion(base::ReadOnlySharedMemoryRegion pdf_page); 103 104 // PrintPreviewUI serves data for chrome://print requests. 105 // 106 // The format for requesting PDF data is as follows: 107 // chrome://print/<PrintPreviewUIID>/<PageIndex>/print.pdf 108 // 109 // Required parameters: 110 // <PrintPreviewUIID> = PrintPreview UI ID 111 // <PageIndex> = Page index is zero-based or 112 // |COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent 113 // a print ready PDF. 114 // 115 // Example: 116 // chrome://print/123/10/print.pdf 117 // 118 // ParseDataPath() takes a path (i.e. what comes after chrome://print/) and 119 // returns true if the path seems to be a valid data path. |ui_id| and 120 // |page_index| are set to the parsed values if the provided pointers aren't 121 // nullptr. 122 static bool ParseDataPath(const std::string& path, 123 int* ui_id, 124 int* page_index); 125 126 // Set initial settings for PrintPreviewUI. 127 static void SetInitialParams( 128 content::WebContents* print_preview_dialog, 129 const PrintHostMsg_RequestPrintPreview_Params& params); 130 131 // Determines whether to cancel a print preview request based on the request 132 // and UI ids in |ids|. 133 // Can be called from any thread. 134 static bool ShouldCancelRequest(const mojom::PreviewIds& ids); 135 136 // Returns an id to uniquely identify this PrintPreviewUI. 137 base::Optional<int32_t> GetIDForPrintPreviewUI() const; 138 139 // Notifies the Web UI of a print preview request with |request_id|. 140 virtual void OnPrintPreviewRequest(int request_id); 141 142 // Notifies the Web UI about the properties of the request preview. 143 void OnDidStartPreview(const mojom::DidStartPreviewParams& params, 144 int request_id); 145 146 // Notifies the Web UI of the default page layout according to the currently 147 // selected printer and page size. 148 void OnDidGetDefaultPageLayout(const mojom::PageSizeMargins& page_layout, 149 const gfx::Rect& printable_area, 150 bool has_custom_page_size_style, 151 int request_id); 152 153 // Notifies the Web UI that the 0-based page |page_number| rendering is being 154 // processed and an OnPendingPreviewPage() call is imminent. Returns whether 155 // |page_number| is the expected page. 156 bool OnPendingPreviewPage(uint32_t page_number); 157 158 // Notifies the Web UI that the 0-based page |page_number| has been rendered. 159 // |preview_request_id| indicates which request resulted in this response. 160 void OnDidPreviewPage(uint32_t page_number, 161 scoped_refptr<base::RefCountedMemory> data, 162 int preview_request_id); 163 164 // Notifies the Web UI renderer that preview data is available. 165 // |preview_request_id| indicates which request resulted in this response. 166 void OnPreviewDataIsAvailable(scoped_refptr<base::RefCountedMemory> data, 167 int preview_request_id); 168 169 // Notifies the Web UI that the print preview failed to render for the request 170 // with id = |request_id|. 171 void OnPrintPreviewFailed(int request_id); 172 173 // Notified the Web UI that this print preview dialog's RenderProcess has been 174 // closed, which may occur for several reasons, e.g. tab closure or crash. 175 void OnPrintPreviewDialogClosed(); 176 177 // Notifies the Web UI that initiator is closed, so we can disable all the 178 // controls that need the initiator for generating the preview data. 179 void OnInitiatorClosed(); 180 181 // Notifies the Web UI to cancel the pending preview request. 182 virtual void OnCancelPendingPreviewRequest(); 183 184 // Hides the print preview dialog. 185 virtual void OnHidePreviewDialog(); 186 187 // Closes the print preview dialog. 188 virtual void OnClosePrintPreviewDialog(); 189 190 // Allows tests to wait until the print preview dialog is loaded. 191 class TestDelegate { 192 public: 193 virtual void DidGetPreviewPageCount(uint32_t page_count) = 0; 194 virtual void DidRenderPreviewPage(content::WebContents* preview_dialog) = 0; 195 196 protected: 197 virtual ~TestDelegate() = default; 198 }; 199 200 static void SetDelegateForTesting(TestDelegate* delegate); 201 202 // Allows for tests to set a file path to print a PDF to. This also initiates 203 // the printing without having to click a button on the print preview dialog. 204 void SetSelectedFileForTesting(const base::FilePath& path); 205 206 // Passes |closure| to PrintPreviewHandler::SetPdfSavedClosureForTesting(). 207 void SetPdfSavedClosureForTesting(base::OnceClosure closure); 208 209 // Tell the handler to send the enable-manipulate-settings-for-test WebUI 210 // event. 211 void SendEnableManipulateSettingsForTest(); 212 213 // Tell the handler to send the manipulate-settings-for-test WebUI event 214 // to set the print preview settings contained in |settings|. 215 void SendManipulateSettingsForTest(const base::DictionaryValue& settings); 216 217 // See SetPrintPreviewDataForIndex(). 218 void SetPrintPreviewDataForIndexForTest( 219 int index, 220 scoped_refptr<base::RefCountedMemory> data); 221 222 // See ClearAllPreviewData(). 223 void ClearAllPreviewDataForTest(); 224 225 // Sets a new valid Print Preview UI ID for this instance. Called by 226 // PrintPreviewHandler in OnJavascriptAllowed(). 227 void SetPreviewUIId(); 228 229 // Clears the UI ID. Called by PrintPreviewHandler in 230 // OnJavascriptDisallowed(). 231 void ClearPreviewUIId(); 232 233 protected: 234 // Alternate constructor for tests 235 PrintPreviewUI(content::WebUI* web_ui, 236 std::unique_ptr<PrintPreviewHandler> handler); 237 238 private: 239 FRIEND_TEST_ALL_PREFIXES(PrintPreviewDialogControllerUnitTest, 240 TitleAfterReload); 241 242 // Sets the print preview |data|. |index| is zero-based, and can be 243 // |COMPLETE_PREVIEW_DOCUMENT_INDEX| to set the entire preview document. 244 void SetPrintPreviewDataForIndex(int index, 245 scoped_refptr<base::RefCountedMemory> data); 246 247 // Clear the existing print preview data. 248 void ClearAllPreviewData(); 249 250 base::TimeTicks initial_preview_start_time_; 251 252 // The unique ID for this class instance. Stored here to avoid calling 253 // GetIDForPrintPreviewUI() everywhere. 254 base::Optional<int32_t> id_; 255 256 // Weak pointer to the WebUI handler. 257 PrintPreviewHandler* const handler_; 258 259 // Indicates whether the source document is from ARC. 260 bool source_is_arc_ = false; 261 262 // Indicates whether the source document can be modified. 263 bool source_is_modifiable_ = true; 264 265 // Indicates whether the source document is a PDF. 266 bool source_is_pdf_ = false; 267 268 // Indicates whether the source document has selection. 269 bool source_has_selection_ = false; 270 271 // Indicates whether only the selection should be printed. 272 bool print_selection_only_ = false; 273 274 // Keeps track of whether OnClosePrintPreviewDialog() has been called or not. 275 bool dialog_closed_ = false; 276 277 // Store the initiator title, used for populating the print preview dialog 278 // title. 279 base::string16 initiator_title_; 280 281 // The list of 0-based page numbers that will be rendered. 282 std::vector<uint32_t> pages_to_render_; 283 284 // The list of pages to be converted. 285 std::vector<base::ReadOnlySharedMemoryRegion> pages_for_nup_convert_; 286 287 // Index into |pages_to_render_| for the page number to expect. 288 size_t pages_to_render_index_ = 0; 289 290 // number of pages per sheet and should be greater or equal to 1. 291 int pages_per_sheet_ = 1; 292 293 // Physical size of the page, including non-printable margins. 294 gfx::Size page_size_; 295 296 // The printable area of the printed document pages. 297 gfx::Rect printable_area_; 298 299 mojo::AssociatedReceiver<mojom::PrintPreviewUI> receiver_{this}; 300 301 DISALLOW_COPY_AND_ASSIGN(PrintPreviewUI); 302 }; 303 304 } // namespace printing 305 306 #endif // CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_PRINT_PREVIEW_UI_H_ 307