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

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: Removed unnecessary comment. 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 (c) 2014 The Chromium Authors. All rights reserved.
Lei Zhang 2014/06/24 21:24:58 No (c), forgot to tell you last time.
ivandavid 2014/06/24 22:55:48 Done.
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/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/path_service.h"
16 #include "base/run_loop.h"
17 #include "base/strings/string_util.h"
18 #include "chrome/app/chrome_command_ids.h"
19 #include "chrome/browser/net/referrer.h"
20 #include "chrome/browser/printing/print_preview_dialog_controller.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/ui/browser.h"
23 #include "chrome/browser/ui/browser_commands.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h"
26 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
27 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
28 #include "chrome/common/chrome_paths.h"
29 #include "chrome/common/print_messages.h"
30 #include "chrome/common/url_constants.h"
31 #include "chrome/test/base/in_process_browser_test.h"
32 #include "chrome/test/base/ui_test_utils.h"
33 #include "content/public/browser/web_contents.h"
34 #include "content/public/browser/web_ui_message_handler.h"
35 #include "content/public/common/page_transition_types.h"
36 #include "content/public/test/browser_test_utils.h"
37 #include "content/public/test/test_navigation_observer.h"
38 #include "content/public/test/test_utils.h"
39 #include "printing/print_job_constants.h"
40 #include "ui/events/keycodes/keyboard_codes.h"
41 #include "url/gurl.h"
42 #include "ipc/ipc_message_macros.h"
43
44 using content::WebContents;
45 using content::WebContentsObserver;
46
47 class PrintPreviewObserver;
48 class UIDoneLoadingMessageHandler;
49
50 // Message refers to the 'UILoaded' message from print_preview.js.
51 // It gets sent either from onPreviewGenerationDone or from
52 // onManipulateSettings_() in print_preview.js
53 enum State {
54 // Waiting for the first message so the program can select Save as PDF
55 kWaitingToSendSaveAsPdf = 0,
56 // Waiting for the second message so the test can set the layout
57 kWaitingToSendLayoutSettings = 1,
58 // Waiting for the third message so the test can set the page numbers
59 kWaitingToSendPageNumbers = 2,
60 // Waiting for the forth message so the test can set the headers checkbox
61 kWaitingToSendHeadersAndFooters = 3,
62 // Waiting for the fifth message so the test can set the background checkbox
63 kWaitingToSendBackgroundColorsAndImages = 4,
64 // Waiting for the sixth message so the test can set the margins combobox
65 kWaitingToSendMargins = 5,
66 // Waiting for the final message so the program can save to PDF.
67 kWaitingForFinalMessage = 6,
68 };
69
70 class PrintPreviewObserver : public WebContentsObserver {
71 public:
72 PrintPreviewObserver(WebContents* dialog, Browser* browser)
73 : WebContentsObserver(dialog), browser_(browser), is_portrait_(true),
74 headers_and_footers_(true), background_colors_and_images_(false),
75 margins_(printing::DEFAULT_MARGINS) {}
Dan Beam 2014/06/24 22:55:16 nit: each on a separate line
ivandavid 2014/06/25 00:02:21 Done.
76
77 virtual ~PrintPreviewObserver() {}
78
79 // Sets closure for the observer so that it can end the loop.
80 void set_quit_closure(const base::Closure &closure) {
81 closure_ = closure;
82 }
83
84 // Actually stops the message_loop so that the test can proceed.
85 void EndLoop() {
86 base::MessageLoop::current()->PostTask(FROM_HERE, closure_);
87 }
88
89 bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
90 IPC_BEGIN_MESSAGE_MAP(PrintPreviewObserver, message)
91 IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount,
92 OnDidGetPreviewPageCount)
93 IPC_MESSAGE_UNHANDLED(return false;)
94 IPC_END_MESSAGE_MAP();
95 return false;
96 }
97
98 // Gets the PrintPreviewUI so that certain elements can be accessed.
99 PrintPreviewUI* GetUI() {
100 return ui_;
101 }
102
103 // Returns the web_contents of the print preview dialog.
104 WebContents* GetPreviewContents() {
105 return web_contents_;
106 }
107
108 // Calls a javascript function that will change the print preview settings,
109 // such as the layout, the margins, page numbers, etc.
110 void ManipulatePreviewSettings(State state) {
111 std::vector<const base::Value*> args;
112 script_argument_.reset(new base::DictionaryValue());
113 if (state == kWaitingToSendSaveAsPdf) {
114 script_argument_->SetBoolean("selectSaveAsPdfDestination", true);
115 } else if (state == kWaitingToSendLayoutSettings) {
116 script_argument_->SetBoolean("layoutSettings.portrait", is_portrait_);
117 } else if (state == kWaitingToSendPageNumbers) {
118 script_argument_->SetString("pageRange", page_numbers_);
119 } else if (state == kWaitingToSendHeadersAndFooters) {
120 script_argument_->SetBoolean("headersAndFooters", headers_and_footers_);
121 } else if (state == kWaitingToSendBackgroundColorsAndImages) {
122 script_argument_->SetBoolean("backgroundColorsAndImages",
123 background_colors_and_images_);
124 } else if (state == kWaitingToSendMargins) {
125 script_argument_->SetInteger("margins", margins_);
126 }
127
128 args.push_back(script_argument_.get());
129 DCHECK(!script_argument_->empty());
130 DCHECK(!args.empty());
131 ui_->web_ui()->CallJavascriptFunction("onManipulateSettingsForTest", args);
132 }
133
134 // Function to set the print preview settings and save them so they
135 // can be sent later. Currently only used in the constructor. Will be
136 // used when creating a test and take command line arguments.
137 // |page_numbers| is a comma separated page range.
138 // Example: "1-5,9" will print pages 1 through 5 and page 9.
139 // The pages specified must be less than or equal to the maximum
140 // page number. An empty string seems to be valid input, however
141 // further testing will be required to see if that is actually
142 // true.
143 void SetPrintPreviewSettings(bool is_portrait,
144 const std::string& page_numbers,
145 bool headers_and_footers,
146 bool background_colors_and_images,
147 printing::MarginType margins) {
148 is_portrait_ = is_portrait;
149 page_numbers_ = page_numbers;
150 headers_and_footers_ = headers_and_footers;
151 background_colors_and_images_ = background_colors_and_images;
152 margins_ = margins;
153 }
154
155 private:
156 // Called when the observer gets the IPC message stating that the
157 // page count is ready.
158 void OnDidGetPreviewPageCount(
159 const PrintHostMsg_DidGetPreviewPageCount_Params &params);
160
161 void DidCloneToNewWebContents(WebContents* old_web_contents,
162 WebContents* new_web_contents)
163 OVERRIDE {
164 Observe(new_web_contents);
Lei Zhang 2014/06/24 21:24:58 In patch set 16, I asked if this should only be ca
ivandavid 2014/06/24 22:55:48 I think I'll just leave it like it is for now, but
165 }
166
167 void WebContentsDestroyed() OVERRIDE {
168 EndLoop();
169 }
170
171 Browser* browser_;
172 base::Closure closure_;
173 WebContents* web_contents_;
Dan Beam 2014/06/24 22:55:16 not initialized, would crash if dereferenced
ivandavid 2014/06/25 00:02:21 Done.
ivandavid 2014/06/25 00:02:21 Removed the variable. Turns out it was unnecessary
174
175 PrintPreviewUI* ui_;
Dan Beam 2014/06/24 22:55:16 not initialized, would crash if deferenced
ivandavid 2014/06/25 00:02:21 Same change as for web_contents_. Done.
176
177 scoped_ptr<PrintPreviewObserver> print_preview_observer_;
Lei Zhang 2014/06/24 21:24:58 Why does PrintPreviewObserver own another PrintPre
ivandavid 2014/06/24 22:55:48 I think it was a copy paste accident.
ivandavid 2014/06/24 22:55:48 Done.
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);
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 base::FilePath pdf_file_save_path;
276 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &pdf_file_save_path));
277 pdf_file_save_path = pdf_file_save_path.AppendASCII("printing");
278 pdf_file_save_path = pdf_file_save_path.AppendASCII("dummy.pdf");
279
280 base::RunLoop loop;
281 print_preview_observer_->set_quit_closure(loop.QuitClosure());
282 print_preview_observer_->GetUI()->handler_->
283 FileSelected(pdf_file_save_path, 0, NULL);
284 loop.Run();
285 }
286
287 private:
288 virtual void SetUpOnMainThread() OVERRIDE {
289 WebContents* tab =
290 browser()->tab_strip_model()->GetActiveWebContents();
291 ASSERT_TRUE(tab);
292
293 print_preview_observer_.reset(new PrintPreviewObserver(tab, browser()));
294 chrome::DuplicateTab(browser());
295
296 WebContents* initiator_ =
297 browser()->tab_strip_model()->GetActiveWebContents();
298 ASSERT_TRUE(initiator_);
299 ASSERT_NE(tab, initiator_);
300 }
301
302 virtual void CleanUpOnMainThread() OVERRIDE {
303 print_preview_observer_.reset();
304 }
305
306 scoped_ptr<PrintPreviewObserver> print_preview_observer_;
307
308 DISALLOW_COPY_AND_ASSIGN(PrintPreviewPdfGeneratedBrowserTest);
309 };
310
311 IN_PROC_BROWSER_TEST_F(PrintPreviewPdfGeneratedBrowserTest, DummyTest) {
312 // TODO(ivandavid): Make this work on Windows also. Windows doesn't have
313 // the same directory structure.
314
315 // If the layout tests are run and then this test is run in isolation, it
316 // will behave as if the layout test framework launched it, because this
317 // file is not currently being cleaned up by the layout test framework.
318 // It will be fixed.
319 bool in_layout_test =
320 freopen("/tmp/pdf_generated_browsertest/stdin.txt", "r", stdin)
Lei Zhang 2014/06/24 21:24:58 Don't do this. It's hacky. I think this test shoul
ivandavid 2014/06/24 22:55:48 Done.
ivandavid 2014/06/24 22:55:48 I made it so that it automatically assumes that it
321 ? true : false;
322 std::string cmd;
323
324 if (in_layout_test) {
325 // The printf and fflush is necessary as it seems to be 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 getline(std::cin, cmd);
Lei Zhang 2014/06/24 21:24:58 std::getline, so you don't confuse this with getli
ivandavid 2014/06/24 22:55:48 Done.
334 if (cmd.size() == 0) {
Lei Zhang 2014/06/24 21:24:58 std::string::size() == 0 -> std::string::empty()
ivandavid 2014/06/24 22:55:48 Done.
335 while (std::cin.eof()) {
336 std::cin.clear();
337 getline(std::cin, cmd);
338 if (cmd.size() > 0) {
339 LOG(ERROR) << cmd;
340 break;
341 }
342 }
343 } else {
344 LOG(ERROR) << cmd;
345 }
346 }
347
348 // TODO(ivandavid): Read from cmd the name of the test html file.
Lei Zhang 2014/06/24 21:24:58 If you want to be content_shell compatible, you ma
ivandavid 2014/06/24 22:55:48 I am not completely sure how it works when running
349 base::FilePath::StringType test_name("test2.html");
350 NavigateAndPreview(test_name);
351 Print();
352
353 // Tells the layout tests that everything is done.
354 // In the future, before this part, PNG data will be sent from this program
355 // to the layout tests through stdout.
356 if (in_layout_test) {
357 printf("#EOF\n");
358 fflush(stdout);
359
360 // Send image data before this EOF.
361 printf("#EOF\n");
362 fflush(stdout);
363 fprintf(stderr, "#EOF\n");
364 }
365 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698