Popular sites on the NTP: re-download popular suggestions once per Chrome run
[chromium-blink-merge.git] / chrome / browser / printing / print_preview_dialog_controller_browsertest.cc
blob191e67403ce8ab3a888affadbdd1c0de0b94076e
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.
5 #include "base/bind_helpers.h"
6 #include "base/location.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
13 #include "chrome/browser/plugins/plugin_prefs.h"
14 #include "chrome/browser/printing/print_preview_dialog_controller.h"
15 #include "chrome/browser/task_management/task_management_browsertest_util.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_commands.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "chrome/common/chrome_content_client.h"
20 #include "chrome/common/url_constants.h"
21 #include "chrome/grit/generated_resources.h"
22 #include "chrome/test/base/in_process_browser_test.h"
23 #include "chrome/test/base/ui_test_utils.h"
24 #include "components/printing/common/print_messages.h"
25 #include "content/public/browser/plugin_service.h"
26 #include "content/public/browser/render_frame_host.h"
27 #include "content/public/browser/render_process_host.h"
28 #include "content/public/browser/web_contents_observer.h"
29 #include "content/public/test/browser_test_utils.h"
30 #include "ipc/ipc_message_macros.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "url/gurl.h"
34 using content::WebContents;
35 using content::WebContentsObserver;
37 namespace {
39 class RequestPrintPreviewObserver : public WebContentsObserver {
40 public:
41 explicit RequestPrintPreviewObserver(WebContents* dialog)
42 : WebContentsObserver(dialog) {
44 ~RequestPrintPreviewObserver() override {}
46 void set_quit_closure(const base::Closure& quit_closure) {
47 quit_closure_ = quit_closure;
50 private:
51 // content::WebContentsObserver implementation.
52 bool OnMessageReceived(const IPC::Message& message) override {
53 IPC_BEGIN_MESSAGE_MAP(RequestPrintPreviewObserver, message)
54 IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
55 OnRequestPrintPreview)
56 IPC_MESSAGE_UNHANDLED(break;)
57 IPC_END_MESSAGE_MAP();
58 return false; // Report not handled so the real handler receives it.
61 void OnRequestPrintPreview(
62 const PrintHostMsg_RequestPrintPreview_Params& /* params */) {
63 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
66 base::Closure quit_closure_;
68 DISALLOW_COPY_AND_ASSIGN(RequestPrintPreviewObserver);
71 class PrintPreviewDialogClonedObserver : public WebContentsObserver {
72 public:
73 explicit PrintPreviewDialogClonedObserver(WebContents* dialog)
74 : WebContentsObserver(dialog) {
76 ~PrintPreviewDialogClonedObserver() override {}
78 RequestPrintPreviewObserver* request_preview_dialog_observer() {
79 return request_preview_dialog_observer_.get();
82 private:
83 // content::WebContentsObserver implementation.
84 void DidCloneToNewWebContents(WebContents* old_web_contents,
85 WebContents* new_web_contents) override {
86 request_preview_dialog_observer_.reset(
87 new RequestPrintPreviewObserver(new_web_contents));
90 scoped_ptr<RequestPrintPreviewObserver> request_preview_dialog_observer_;
92 DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogClonedObserver);
95 class PrintPreviewDialogDestroyedObserver : public WebContentsObserver {
96 public:
97 explicit PrintPreviewDialogDestroyedObserver(WebContents* dialog)
98 : WebContentsObserver(dialog),
99 dialog_destroyed_(false) {
101 ~PrintPreviewDialogDestroyedObserver() override {}
103 bool dialog_destroyed() const { return dialog_destroyed_; }
105 private:
106 // content::WebContentsObserver implementation.
107 void WebContentsDestroyed() override { dialog_destroyed_ = true; }
109 bool dialog_destroyed_;
111 DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogDestroyedObserver);
114 void PluginsLoadedCallback(
115 const base::Closure& quit_closure,
116 const std::vector<content::WebPluginInfo>& /* info */) {
117 quit_closure.Run();
120 bool GetPdfPluginInfo(content::WebPluginInfo* info) {
121 base::FilePath pdf_plugin_path = base::FilePath::FromUTF8Unsafe(
122 ChromeContentClient::kPDFPluginPath);
123 return content::PluginService::GetInstance()->GetPluginInfoByPath(
124 pdf_plugin_path, info);
127 const char kDummyPrintUrl[] = "chrome://print/dummy.pdf";
129 void CountFrames(int* frame_count,
130 content::RenderFrameHost* frame) {
131 ++(*frame_count);
134 void CheckPdfPluginForRenderFrame(content::RenderFrameHost* frame) {
135 content::WebPluginInfo pdf_plugin_info;
136 ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));
138 ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
139 EXPECT_TRUE(filter->IsPluginAvailable(
140 frame->GetProcess()->GetID(),
141 frame->GetRoutingID(),
142 nullptr,
143 GURL(kDummyPrintUrl),
144 GURL(),
145 &pdf_plugin_info));
148 } // namespace
150 class PrintPreviewDialogControllerBrowserTest : public InProcessBrowserTest {
151 public:
152 PrintPreviewDialogControllerBrowserTest() : initiator_(nullptr) {}
153 ~PrintPreviewDialogControllerBrowserTest() override {}
155 WebContents* initiator() {
156 return initiator_;
159 void PrintPreview() {
160 base::RunLoop run_loop;
161 request_preview_dialog_observer()->set_quit_closure(run_loop.QuitClosure());
162 chrome::Print(browser());
163 run_loop.Run();
166 WebContents* GetPrintPreviewDialog() {
167 printing::PrintPreviewDialogController* dialog_controller =
168 printing::PrintPreviewDialogController::GetInstance();
169 return dialog_controller->GetPrintPreviewForContents(initiator_);
172 private:
173 void SetUpOnMainThread() override {
174 WebContents* first_tab =
175 browser()->tab_strip_model()->GetActiveWebContents();
176 ASSERT_TRUE(first_tab);
178 // Open a new tab so |cloned_tab_observer_| can see it first and attach a
179 // RequestPrintPreviewObserver to it before the real
180 // PrintPreviewMessageHandler gets created. Thus enabling
181 // RequestPrintPreviewObserver to get messages first for the purposes of
182 // this test.
183 cloned_tab_observer_.reset(new PrintPreviewDialogClonedObserver(first_tab));
184 chrome::DuplicateTab(browser());
186 initiator_ = browser()->tab_strip_model()->GetActiveWebContents();
187 ASSERT_TRUE(initiator_);
188 ASSERT_NE(first_tab, initiator_);
190 content::PluginService::GetInstance()->Init();
191 content::PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
194 void TearDownOnMainThread() override {
195 cloned_tab_observer_.reset();
196 initiator_ = nullptr;
199 RequestPrintPreviewObserver* request_preview_dialog_observer() {
200 return cloned_tab_observer_->request_preview_dialog_observer();
203 scoped_ptr<PrintPreviewDialogClonedObserver> cloned_tab_observer_;
204 WebContents* initiator_;
206 DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogControllerBrowserTest);
209 // Test to verify that when a initiator navigates, we can create a new preview
210 // dialog for the new tab contents.
211 // http://crbug.com/377337
212 #if defined(OS_WIN)
213 #define MAYBE_NavigateFromInitiatorTab DISABLED_NavigateFromInitiatorTab
214 #else
215 #define MAYBE_NavigateFromInitiatorTab NavigateFromInitiatorTab
216 #endif
217 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
218 MAYBE_NavigateFromInitiatorTab) {
219 // Print for the first time.
220 PrintPreview();
222 // Get the preview dialog for the initiator tab.
223 WebContents* preview_dialog = GetPrintPreviewDialog();
225 // Check a new print preview dialog got created.
226 ASSERT_TRUE(preview_dialog);
227 ASSERT_NE(initiator(), preview_dialog);
229 // Navigate in the initiator tab. Make sure navigating destroys the print
230 // preview dialog.
231 PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
232 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
233 ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());
235 // Try printing again.
236 PrintPreview();
238 // Get the print preview dialog for the initiator tab.
239 WebContents* new_preview_dialog = GetPrintPreviewDialog();
241 // Check a new preview dialog got created.
242 EXPECT_TRUE(new_preview_dialog);
245 // Test to verify that after reloading the initiator, it creates a new print
246 // preview dialog.
247 // http://crbug.com/377337
248 #if defined(OS_WIN)
249 #define MAYBE_ReloadInitiatorTab DISABLED_ReloadInitiatorTab
250 #else
251 #define MAYBE_ReloadInitiatorTab ReloadInitiatorTab
252 #endif
253 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
254 MAYBE_ReloadInitiatorTab) {
255 // Print for the first time.
256 PrintPreview();
258 WebContents* preview_dialog = GetPrintPreviewDialog();
260 // Check a new print preview dialog got created.
261 ASSERT_TRUE(preview_dialog);
262 ASSERT_NE(initiator(), preview_dialog);
264 // Reload the initiator. Make sure reloading destroys the print preview
265 // dialog.
266 PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
267 chrome::Reload(browser(), CURRENT_TAB);
268 content::WaitForLoadStop(
269 browser()->tab_strip_model()->GetActiveWebContents());
270 ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());
272 // Try printing again.
273 PrintPreview();
275 // Create a preview dialog for the initiator tab.
276 WebContents* new_preview_dialog = GetPrintPreviewDialog();
277 EXPECT_TRUE(new_preview_dialog);
280 // Test to verify that after print preview works even when the PDF plugin is
281 // disabled for webpages.
282 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
283 PdfPluginDisabled) {
284 // Make sure plugins are loaded.
286 base::RunLoop run_loop;
287 content::PluginService::GetInstance()->GetPlugins(
288 base::Bind(&PluginsLoadedCallback, run_loop.QuitClosure()));
289 run_loop.Run();
291 // Get the PDF plugin info.
292 content::WebPluginInfo pdf_plugin_info;
293 ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));
295 // Disable the PDF plugin.
296 PluginPrefs::GetForProfile(browser()->profile())->EnablePluginGroup(
297 false, base::ASCIIToUTF16(ChromeContentClient::kPDFPluginName));
299 // Make sure it is actually disabled for webpages.
300 ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
301 content::WebPluginInfo dummy_pdf_plugin_info = pdf_plugin_info;
302 EXPECT_FALSE(filter->IsPluginAvailable(
303 initiator()->GetRenderProcessHost()->GetID(),
304 initiator()->GetMainFrame()->GetRoutingID(),
305 nullptr,
306 GURL("http://google.com"),
307 GURL(),
308 &dummy_pdf_plugin_info));
310 PrintPreview();
312 // Check a new print preview dialog got created.
313 WebContents* preview_dialog = GetPrintPreviewDialog();
314 ASSERT_TRUE(preview_dialog);
315 ASSERT_NE(initiator(), preview_dialog);
317 // Wait until the <iframe> in the print preview renderer has loaded.
318 // |frame_count| should be 2. The other frame is the main frame.
319 const int kExpectedFrameCount = 2;
320 int frame_count;
321 do {
322 base::RunLoop run_loop;
323 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
324 FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(1));
325 run_loop.Run();
327 frame_count = 0;
328 preview_dialog->ForEachFrame(
329 base::Bind(&CountFrames, base::Unretained(&frame_count)));
330 } while (frame_count < kExpectedFrameCount);
331 ASSERT_EQ(kExpectedFrameCount, frame_count);
333 // Make sure all the frames in the dialog has access to the PDF plugin.
334 preview_dialog->ForEachFrame(base::Bind(&CheckPdfPluginForRenderFrame));
337 #if defined(ENABLE_TASK_MANAGER)
339 namespace {
341 base::string16 GetExpectedPrefix() {
342 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX,
343 base::string16());
346 const std::vector<task_management::WebContentsTag*>& GetTrackedTags() {
347 return task_management::WebContentsTagsManager::GetInstance()->
348 tracked_tags();
351 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
352 TaskManagementTest) {
353 // This test starts with two tabs open.
354 EXPECT_EQ(2U, GetTrackedTags().size());
356 PrintPreview();
357 EXPECT_EQ(3U, GetTrackedTags().size());
359 // Create a task manager and expect the pre-existing print previews are
360 // provided.
361 task_management::MockWebContentsTaskManager task_manager;
362 EXPECT_TRUE(task_manager.tasks().empty());
363 task_manager.StartObserving();
364 EXPECT_EQ(3U, task_manager.tasks().size());
365 const task_management::Task* pre_existing_task = task_manager.tasks().back();
366 EXPECT_EQ(task_management::Task::RENDERER, pre_existing_task->GetType());
367 const base::string16 pre_existing_title = pre_existing_task->title();
368 const base::string16 expected_prefix = GetExpectedPrefix();
369 EXPECT_TRUE(base::StartsWith(pre_existing_title,
370 expected_prefix,
371 base::CompareCase::INSENSITIVE_ASCII));
373 // Navigating away from the current page in the current tab for which a print
374 // preview is displayed will cancel the print preview and hence the task
375 // manger shouldn't show a printing task.
376 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
377 EXPECT_EQ(2U, GetTrackedTags().size());
378 EXPECT_EQ(2U, task_manager.tasks().size());
380 // Now start another print preview after the had already been created and
381 // validated that a corresponding task is reported.
382 PrintPreview();
383 EXPECT_EQ(3U, GetTrackedTags().size());
384 EXPECT_EQ(3U, task_manager.tasks().size());
385 const task_management::Task* task = task_manager.tasks().back();
386 EXPECT_EQ(task_management::Task::RENDERER, task->GetType());
387 const base::string16 title = task->title();
388 EXPECT_TRUE(base::StartsWith(title,
389 expected_prefix,
390 base::CompareCase::INSENSITIVE_ASCII));
393 } // namespace
395 #endif // defined(ENABLE_TASK_MANAGER)