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