Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: chrome/browser/printing/print_preview_pdf_generated_browsertest.cc

Issue 335583004: Added a test that currently is able to print to pdf. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Made browsertest assume layout test launched it. Fixed style and consistency issues in javascript files. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 #include <cstdio>
6 #include <iostream>
7 #include <limits>
8 #include <string>
9 #include <vector>
10 #include <unistd.h>
11
12 #include "base/files/file_path.h"
13 #include "base/files/file.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/path_service.h"
17 #include "base/run_loop.h"
18 #include "base/strings/string_util.h"
19 #include "chrome/app/chrome_command_ids.h"
20 #include "chrome/browser/net/referrer.h"
21 #include "chrome/browser/printing/print_preview_dialog_controller.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_commands.h"
25 #include "chrome/browser/ui/tabs/tab_strip_model.h"
26 #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h"
27 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
28 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
29 #include "chrome/common/chrome_paths.h"
30 #include "chrome/common/print_messages.h"
31 #include "chrome/common/url_constants.h"
32 #include "chrome/test/base/in_process_browser_test.h"
33 #include "chrome/test/base/ui_test_utils.h"
34 #include "content/public/browser/web_contents.h"
35 #include "content/public/browser/web_ui_message_handler.h"
36 #include "content/public/common/page_transition_types.h"
37 #include "content/public/test/browser_test_utils.h"
38 #include "content/public/test/test_navigation_observer.h"
39 #include "content/public/test/test_utils.h"
40 #include "printing/print_job_constants.h"
41 #include "ui/events/keycodes/keyboard_codes.h"
42 #include "url/gurl.h"
43 #include "ipc/ipc_message_macros.h"
44
45 using content::WebContents;
46 using content::WebContentsObserver;
47
48 class PrintPreviewObserver;
49 class UIDoneLoadingMessageHandler;
50
51 // Message refers to the 'UILoaded' message from print_preview.js.
52 // It gets sent either from onPreviewGenerationDone or from
53 // onManipulateSettings_() in print_preview.js
54 enum State {
55 // Waiting for the first message so the program can select Save as PDF
56 kWaitingToSendSaveAsPdf = 0,
57 // Waiting for the second message so the test can set the layout
58 kWaitingToSendLayoutSettings = 1,
59 // Waiting for the third message so the test can set the page numbers
60 kWaitingToSendPageNumbers = 2,
61 // Waiting for the forth message so the test can set the headers checkbox
62 kWaitingToSendHeadersAndFooters = 3,
63 // Waiting for the fifth message so the test can set the background checkbox
64 kWaitingToSendBackgroundColorsAndImages = 4,
65 // Waiting for the sixth message so the test can set the margins combobox
66 kWaitingToSendMargins = 5,
67 // Waiting for the final message so the program can save to PDF.
68 kWaitingForFinalMessage = 6,
69 };
70
71 class PrintPreviewObserver : public WebContentsObserver {
72 public:
73 PrintPreviewObserver(WebContents* dialog, Browser* browser)
74 : WebContentsObserver(dialog), browser_(browser), is_portrait_(true),
75 headers_and_footers_(true), background_colors_and_images_(false),
76 margins_(printing::DEFAULT_MARGINS) {}
77
78 virtual ~PrintPreviewObserver() {}
79
80 // Sets closure for the observer so that it can end the loop.
81 void set_quit_closure(const base::Closure &closure) {
82 closure_ = closure;
83 }
84
85 // Actually stops the message_loop so that the test can proceed.
86 void EndLoop() {
87 base::MessageLoop::current()->PostTask(FROM_HERE, closure_);
88 }
89
90 bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
Dan Beam 2014/06/24 23:13:01 most common way to do this: bool handled = true
ivandavid 2014/06/25 00:02:21 I am using the same format as the OnMessageReceive
Dan Beam 2014/06/25 00:13:31 the method I suggested does return false
91 IPC_BEGIN_MESSAGE_MAP(PrintPreviewObserver, message)
92 IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount,
93 OnDidGetPreviewPageCount)
94 IPC_MESSAGE_UNHANDLED(return false;)
95 IPC_END_MESSAGE_MAP();
96 return false;
97 }
98
99 // Gets the PrintPreviewUI so that certain elements can be accessed.
100 PrintPreviewUI* GetUI() {
101 return ui_;
102 }
103
104 // Returns the web_contents of the print preview dialog.
105 WebContents* GetPreviewContents() {
106 return web_contents_;
107 }
108
109 // Calls a javascript function that will change the print preview settings,
110 // such as the layout, the margins, page numbers, etc.
111 void ManipulatePreviewSettings(State state) {
112 std::vector<const base::Value*> args;
113 script_argument_.reset(new base::DictionaryValue());
114 if (state == kWaitingToSendSaveAsPdf) {
115 script_argument_->SetBoolean("selectSaveAsPdfDestination", true);
116 } else if (state == kWaitingToSendLayoutSettings) {
117 script_argument_->SetBoolean("layoutSettings.portrait", is_portrait_);
118 } else if (state == kWaitingToSendPageNumbers) {
119 script_argument_->SetString("pageRange", page_numbers_);
120 } else if (state == kWaitingToSendHeadersAndFooters) {
121 script_argument_->SetBoolean("headersAndFooters", headers_and_footers_);
122 } else if (state == kWaitingToSendBackgroundColorsAndImages) {
123 script_argument_->SetBoolean("backgroundColorsAndImages",
124 background_colors_and_images_);
125 } else if (state == kWaitingToSendMargins) {
126 script_argument_->SetInteger("margins", margins_);
127 }
128
129 args.push_back(script_argument_.get());
130 DCHECK(!script_argument_->empty());
131 DCHECK(!args.empty());
132 ui_->web_ui()->CallJavascriptFunction("onManipulateSettingsForTest", args);
133 }
134
135 // Function to set the print preview settings and save them so they
136 // can be sent later. Currently only used in the constructor. Will be
137 // used when creating a test and take command line arguments.
138 // |page_numbers| is a comma separated page range.
139 // Example: "1-5,9" will print pages 1 through 5 and page 9.
140 // The pages specified must be less than or equal to the maximum
141 // page number. An empty string seems to be valid input, however
142 // further testing will be required to see if that is actually
143 // true.
144 void SetPrintPreviewSettings(bool is_portrait,
145 const std::string& page_numbers,
146 bool headers_and_footers,
147 bool background_colors_and_images,
148 printing::MarginType margins) {
149 is_portrait_ = is_portrait;
150 page_numbers_ = page_numbers;
151 headers_and_footers_ = headers_and_footers;
152 background_colors_and_images_ = background_colors_and_images;
153 margins_ = margins;
154 }
155
156 private:
157 // Called when the observer gets the IPC message stating that the
158 // page count is ready.
159 void OnDidGetPreviewPageCount(
160 const PrintHostMsg_DidGetPreviewPageCount_Params &params);
161
162 void DidCloneToNewWebContents(WebContents* old_web_contents,
163 WebContents* new_web_contents)
164 OVERRIDE {
165 Observe(new_web_contents);
166 }
167
168 void WebContentsDestroyed() OVERRIDE {
169 EndLoop();
170 }
171
172 Browser* browser_;
173 base::Closure closure_;
174 WebContents* web_contents_;
175
176 PrintPreviewUI* ui_;
177
178 scoped_ptr<base::DictionaryValue> script_argument_;
179 bool is_portrait_;
180 std::string page_numbers_;
181 bool headers_and_footers_;
182 bool background_colors_and_images_;
183 printing::MarginType margins_;
184
185 DISALLOW_COPY_AND_ASSIGN(PrintPreviewObserver);
186 };
187
188 class UIDoneLoadingMessageHandler : public content::WebUIMessageHandler {
189 public:
190 explicit UIDoneLoadingMessageHandler(PrintPreviewObserver* observer) :
191 observer_(observer), state_(kWaitingToSendSaveAsPdf) {}
192
193 virtual ~UIDoneLoadingMessageHandler() {
194 observer_ = NULL;
195 }
196
197 void HandleDone(const base::ListValue* /* args */) {
198 if (state_ == kWaitingForFinalMessage) {
199 observer_->EndLoop();
200 } else {
201 observer_->ManipulatePreviewSettings(state_);
202 state_ = static_cast<State>(static_cast<int>(state_) + 1);
203 }
204 }
205
206 void HandleFailure(const base::ListValue* /* args */) {
207 FAIL();
208 }
209
210 void RegisterMessages() OVERRIDE {
211 web_ui()->RegisterMessageCallback(
212 "UILoadedForTest",
213 base::Bind(&UIDoneLoadingMessageHandler::HandleDone,
214 base::Unretained(this)));
215
216 web_ui()->RegisterMessageCallback(
217 "UIFailedLoadingForTest",
218 base::Bind(&UIDoneLoadingMessageHandler::HandleFailure,
219 base::Unretained(this)));
220 }
221
222 private:
223 PrintPreviewObserver* observer_;
224 State state_;
225
226 DISALLOW_COPY_AND_ASSIGN(UIDoneLoadingMessageHandler);
227 };
228
229 void PrintPreviewObserver::OnDidGetPreviewPageCount(
230 const PrintHostMsg_DidGetPreviewPageCount_Params &params) {
231
232 WebContents* tab = browser_->tab_strip_model()->GetActiveWebContents();
233 ASSERT_TRUE(tab);
234 printing::PrintPreviewDialogController* dialog_controller =
235 printing::PrintPreviewDialogController::GetInstance();
236 ASSERT_TRUE(dialog_controller);
237 web_contents_ = dialog_controller->GetPrintPreviewForContents(tab);
238 ASSERT_TRUE(web_contents_);
239 ASSERT_TRUE(printing::PrintPreviewDialogController::
240 IsPrintPreviewDialog(web_contents_));
241 ui_ = static_cast<PrintPreviewUI*>(web_contents_->GetWebUI()->
242 GetController());
243 ASSERT_TRUE(ui_);
244 ASSERT_TRUE(ui_->web_ui());
245 ui_->web_ui()->CallJavascriptFunction("onEnableManipulateSettingsForTest");
246 Observe(web_contents_);
247 UIDoneLoadingMessageHandler* handler = new UIDoneLoadingMessageHandler(this);
248 ui_->web_ui()->AddMessageHandler(handler);
Dan Beam 2014/06/24 23:13:01 nit: just inline |handler|, i.e. ui_->web_ui()-
ivandavid 2014/06/25 00:02:21 Done.
249 }
250
251 class PrintPreviewPdfGeneratedBrowserTest : public InProcessBrowserTest {
252 public:
253 PrintPreviewPdfGeneratedBrowserTest() {}
254 virtual ~PrintPreviewPdfGeneratedBrowserTest() {}
255
256 // TODO (ivandavid): Provide arguments for SetPrintPreviewSettings here.
257 void NavigateAndPreview(const base::FilePath::StringType& file_name) {
258 print_preview_observer_->SetPrintPreviewSettings(false,
259 "",
260 false,
261 false,
262 printing::DEFAULT_MARGINS);
263 base::FilePath directory(FILE_PATH_LITERAL("printing"));
264 base::FilePath file(file_name);
265 ui_test_utils::NavigateToURL(browser(),
266 ui_test_utils::GetTestUrl(directory, file));
267
268 base::RunLoop loop;
269 print_preview_observer_->set_quit_closure(loop.QuitClosure());
270 chrome::Print(browser());
271 loop.Run();
272 }
273
274 void Print() {
275 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &pdf_file_save_path_));
276 pdf_file_save_path_ = pdf_file_save_path_.AppendASCII("printing");
277 pdf_file_save_path_ = pdf_file_save_path_.AppendASCII("dummy.pdf");
278
279 base::RunLoop loop;
280 print_preview_observer_->set_quit_closure(loop.QuitClosure());
281 print_preview_observer_->GetUI()->handler_->
282 FileSelected(pdf_file_save_path_, 0, NULL);
Dan Beam 2014/06/24 23:13:01 nit: print_preview_observer_->GetUI()->handler_
ivandavid 2014/06/25 00:02:21 Done.
283 loop.Run();
284 }
285
286 private:
287 virtual void SetUpOnMainThread() OVERRIDE {
288 WebContents* tab =
289 browser()->tab_strip_model()->GetActiveWebContents();
290 ASSERT_TRUE(tab);
291
292 print_preview_observer_.reset(new PrintPreviewObserver(tab, browser()));
293 chrome::DuplicateTab(browser());
294
295 WebContents* initiator_ =
Dan Beam 2014/06/24 23:13:01 _ only go at the end of private members (so initia
ivandavid 2014/06/25 00:02:21 Done.
296 browser()->tab_strip_model()->GetActiveWebContents();
297 ASSERT_TRUE(initiator_);
298 ASSERT_NE(tab, initiator_);
299 }
300
301 virtual void CleanUpOnMainThread() OVERRIDE {
302 print_preview_observer_.reset();
303 }
304
305 scoped_ptr<PrintPreviewObserver> print_preview_observer_;
306 base::FilePath pdf_file_save_path_;
307
308 DISALLOW_COPY_AND_ASSIGN(PrintPreviewPdfGeneratedBrowserTest);
309 };
310
311 IN_PROC_BROWSER_TEST_F(PrintPreviewPdfGeneratedBrowserTest,
312 DISABLED_DummyTest) {
313 // TODO(ivandavid): Make this work on Windows also. Windows doesn't have
314 // the same directory structure.
315
316 // TODO(ivandavid): Generate the file here, not in the layout test, then
317 // communicate this information to the layout test framework. It has to
318 // be this way, because there doesn't seem to be a way to communicate the
319 // file name from the layout test framework to the browsertest. Do
320 // the cleanup here also. Use mkstemp() for this (maybe chrome has some
321 // way to do this?).
322 ASSERT_TRUE(freopen("/tmp/pdf_generated_browsertest/stdin.txt", "r", stdin));
323 std::string cmd;
324
325 // The printf and fflush is necessary because
326 // otherwise, the layout tests don't seem to get it if I just use logs or
327 // if I just do printf and no fflush().
328 printf("#READY\n");
329 fflush(stdout);
330
331 // Might have to rewrite this one. It might not work in every case.
332 // Works for now though.
333 std::getline(std::cin, cmd);
334 if (cmd.size() == 0) {
335 while (std::cin.eof()) {
336 std::cin.clear();
337 std::getline(std::cin, cmd);
338 if (!cmd.empty()) {
339 break;
340 }
341 }
342 }
343
344 // TODO(ivandavid): Read from cmd the name of the test html file.
345 base::FilePath::StringType test_name("test2.html");
346 NavigateAndPreview(test_name);
347 Print();
348
349 // Tells the layout tests that everything is done.
350 // In the future, before this part, PNG data will be sent from this program
351 // to the layout tests through stdout.
352 printf("#EOF\n");
353 fflush(stdout);
354
355 // Send image data before this EOF.
356 printf("#EOF\n");
357 fflush(stdout);
358 fprintf(stderr, "#EOF\n");
359 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698