Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / printing / print_preview_dialog_controller_browsertest.cc
blob938faae1337f4a1efa3a02b9f80edc1bb1e960e3
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/ui/browser.h"
16 #include "chrome/browser/ui/browser_commands.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/common/chrome_content_client.h"
19 #include "chrome/common/url_constants.h"
20 #include "chrome/test/base/in_process_browser_test.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "components/printing/common/print_messages.h"
23 #include "content/public/browser/plugin_service.h"
24 #include "content/public/browser/render_frame_host.h"
25 #include "content/public/browser/render_process_host.h"
26 #include "content/public/browser/web_contents_observer.h"
27 #include "content/public/test/browser_test_utils.h"
28 #include "ipc/ipc_message_macros.h"
29 #include "url/gurl.h"
31 using content::WebContents;
32 using content::WebContentsObserver;
34 namespace {
36 class RequestPrintPreviewObserver : public WebContentsObserver {
37 public:
38 explicit RequestPrintPreviewObserver(WebContents* dialog)
39 : WebContentsObserver(dialog) {
41 ~RequestPrintPreviewObserver() override {}
43 void set_quit_closure(const base::Closure& quit_closure) {
44 quit_closure_ = quit_closure;
47 private:
48 // content::WebContentsObserver implementation.
49 bool OnMessageReceived(const IPC::Message& message) override {
50 IPC_BEGIN_MESSAGE_MAP(RequestPrintPreviewObserver, message)
51 IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
52 OnRequestPrintPreview)
53 IPC_MESSAGE_UNHANDLED(break;)
54 IPC_END_MESSAGE_MAP();
55 return false; // Report not handled so the real handler receives it.
58 void OnRequestPrintPreview(
59 const PrintHostMsg_RequestPrintPreview_Params& /* params */) {
60 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
63 base::Closure quit_closure_;
65 DISALLOW_COPY_AND_ASSIGN(RequestPrintPreviewObserver);
68 class PrintPreviewDialogClonedObserver : public WebContentsObserver {
69 public:
70 explicit PrintPreviewDialogClonedObserver(WebContents* dialog)
71 : WebContentsObserver(dialog) {
73 ~PrintPreviewDialogClonedObserver() override {}
75 RequestPrintPreviewObserver* request_preview_dialog_observer() {
76 return request_preview_dialog_observer_.get();
79 private:
80 // content::WebContentsObserver implementation.
81 void DidCloneToNewWebContents(WebContents* old_web_contents,
82 WebContents* new_web_contents) override {
83 request_preview_dialog_observer_.reset(
84 new RequestPrintPreviewObserver(new_web_contents));
87 scoped_ptr<RequestPrintPreviewObserver> request_preview_dialog_observer_;
89 DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogClonedObserver);
92 class PrintPreviewDialogDestroyedObserver : public WebContentsObserver {
93 public:
94 explicit PrintPreviewDialogDestroyedObserver(WebContents* dialog)
95 : WebContentsObserver(dialog),
96 dialog_destroyed_(false) {
98 ~PrintPreviewDialogDestroyedObserver() override {}
100 bool dialog_destroyed() const { return dialog_destroyed_; }
102 private:
103 // content::WebContentsObserver implementation.
104 void WebContentsDestroyed() override { dialog_destroyed_ = true; }
106 bool dialog_destroyed_;
108 DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogDestroyedObserver);
111 void PluginsLoadedCallback(
112 const base::Closure& quit_closure,
113 const std::vector<content::WebPluginInfo>& /* info */) {
114 quit_closure.Run();
117 bool GetPdfPluginInfo(content::WebPluginInfo* info) {
118 base::FilePath pdf_plugin_path = base::FilePath::FromUTF8Unsafe(
119 ChromeContentClient::kPDFPluginPath);
120 return content::PluginService::GetInstance()->GetPluginInfoByPath(
121 pdf_plugin_path, info);
124 const char kDummyPrintUrl[] = "chrome://print/dummy.pdf";
126 void CountFrames(int* frame_count,
127 content::RenderFrameHost* frame) {
128 ++(*frame_count);
131 void CheckPdfPluginForRenderFrame(content::RenderFrameHost* frame) {
132 content::WebPluginInfo pdf_plugin_info;
133 ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));
135 ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
136 EXPECT_TRUE(filter->IsPluginAvailable(
137 frame->GetProcess()->GetID(),
138 frame->GetRoutingID(),
139 nullptr,
140 GURL(kDummyPrintUrl),
141 GURL(),
142 &pdf_plugin_info));
145 } // namespace
147 class PrintPreviewDialogControllerBrowserTest : public InProcessBrowserTest {
148 public:
149 PrintPreviewDialogControllerBrowserTest() : initiator_(nullptr) {}
150 ~PrintPreviewDialogControllerBrowserTest() override {}
152 WebContents* initiator() {
153 return initiator_;
156 void PrintPreview() {
157 base::RunLoop run_loop;
158 request_preview_dialog_observer()->set_quit_closure(run_loop.QuitClosure());
159 chrome::Print(browser());
160 run_loop.Run();
163 WebContents* GetPrintPreviewDialog() {
164 printing::PrintPreviewDialogController* dialog_controller =
165 printing::PrintPreviewDialogController::GetInstance();
166 return dialog_controller->GetPrintPreviewForContents(initiator_);
169 private:
170 void SetUpOnMainThread() override {
171 WebContents* first_tab =
172 browser()->tab_strip_model()->GetActiveWebContents();
173 ASSERT_TRUE(first_tab);
175 // Open a new tab so |cloned_tab_observer_| can see it first and attach a
176 // RequestPrintPreviewObserver to it before the real
177 // PrintPreviewMessageHandler gets created. Thus enabling
178 // RequestPrintPreviewObserver to get messages first for the purposes of
179 // this test.
180 cloned_tab_observer_.reset(new PrintPreviewDialogClonedObserver(first_tab));
181 chrome::DuplicateTab(browser());
183 initiator_ = browser()->tab_strip_model()->GetActiveWebContents();
184 ASSERT_TRUE(initiator_);
185 ASSERT_NE(first_tab, initiator_);
187 content::PluginService::GetInstance()->Init();
188 content::PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
191 void TearDownOnMainThread() override {
192 cloned_tab_observer_.reset();
193 initiator_ = nullptr;
196 RequestPrintPreviewObserver* request_preview_dialog_observer() {
197 return cloned_tab_observer_->request_preview_dialog_observer();
200 scoped_ptr<PrintPreviewDialogClonedObserver> cloned_tab_observer_;
201 WebContents* initiator_;
203 DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogControllerBrowserTest);
206 // Test to verify that when a initiator navigates, we can create a new preview
207 // dialog for the new tab contents.
208 // http://crbug.com/377337
209 #if defined(OS_WIN)
210 #define MAYBE_NavigateFromInitiatorTab DISABLED_NavigateFromInitiatorTab
211 #else
212 #define MAYBE_NavigateFromInitiatorTab NavigateFromInitiatorTab
213 #endif
214 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
215 MAYBE_NavigateFromInitiatorTab) {
216 // Print for the first time.
217 PrintPreview();
219 // Get the preview dialog for the initiator tab.
220 WebContents* preview_dialog = GetPrintPreviewDialog();
222 // Check a new print preview dialog got created.
223 ASSERT_TRUE(preview_dialog);
224 ASSERT_NE(initiator(), preview_dialog);
226 // Navigate in the initiator tab. Make sure navigating destroys the print
227 // preview dialog.
228 PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
229 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
230 ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());
232 // Try printing again.
233 PrintPreview();
235 // Get the print preview dialog for the initiator tab.
236 WebContents* new_preview_dialog = GetPrintPreviewDialog();
238 // Check a new preview dialog got created.
239 EXPECT_TRUE(new_preview_dialog);
242 // Test to verify that after reloading the initiator, it creates a new print
243 // preview dialog.
244 // http://crbug.com/377337
245 #if defined(OS_WIN)
246 #define MAYBE_ReloadInitiatorTab DISABLED_ReloadInitiatorTab
247 #else
248 #define MAYBE_ReloadInitiatorTab ReloadInitiatorTab
249 #endif
250 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
251 MAYBE_ReloadInitiatorTab) {
252 // Print for the first time.
253 PrintPreview();
255 WebContents* preview_dialog = GetPrintPreviewDialog();
257 // Check a new print preview dialog got created.
258 ASSERT_TRUE(preview_dialog);
259 ASSERT_NE(initiator(), preview_dialog);
261 // Reload the initiator. Make sure reloading destroys the print preview
262 // dialog.
263 PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
264 chrome::Reload(browser(), CURRENT_TAB);
265 content::WaitForLoadStop(
266 browser()->tab_strip_model()->GetActiveWebContents());
267 ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());
269 // Try printing again.
270 PrintPreview();
272 // Create a preview dialog for the initiator tab.
273 WebContents* new_preview_dialog = GetPrintPreviewDialog();
274 EXPECT_TRUE(new_preview_dialog);
277 // Test to verify that after print preview works even when the PDF plugin is
278 // disabled for webpages.
279 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
280 PdfPluginDisabled) {
281 // Make sure plugins are loaded.
283 base::RunLoop run_loop;
284 content::PluginService::GetInstance()->GetPlugins(
285 base::Bind(&PluginsLoadedCallback, run_loop.QuitClosure()));
286 run_loop.Run();
288 // Get the PDF plugin info.
289 content::WebPluginInfo pdf_plugin_info;
290 ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));
292 // Disable the PDF plugin.
293 PluginPrefs::GetForProfile(browser()->profile())->EnablePluginGroup(
294 false, base::ASCIIToUTF16(ChromeContentClient::kPDFPluginName));
296 // Make sure it is actually disabled for webpages.
297 ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
298 content::WebPluginInfo dummy_pdf_plugin_info = pdf_plugin_info;
299 EXPECT_FALSE(filter->IsPluginAvailable(
300 initiator()->GetRenderProcessHost()->GetID(),
301 initiator()->GetMainFrame()->GetRoutingID(),
302 nullptr,
303 GURL("http://google.com"),
304 GURL(),
305 &dummy_pdf_plugin_info));
307 PrintPreview();
309 // Check a new print preview dialog got created.
310 WebContents* preview_dialog = GetPrintPreviewDialog();
311 ASSERT_TRUE(preview_dialog);
312 ASSERT_NE(initiator(), preview_dialog);
314 // Wait until the <iframe> in the print preview renderer has loaded.
315 // |frame_count| should be 2. The other frame is the main frame.
316 const int kExpectedFrameCount = 2;
317 int frame_count;
318 do {
319 base::RunLoop run_loop;
320 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
321 FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(1));
322 run_loop.Run();
324 frame_count = 0;
325 preview_dialog->ForEachFrame(
326 base::Bind(&CountFrames, base::Unretained(&frame_count)));
327 } while (frame_count < kExpectedFrameCount);
328 ASSERT_EQ(kExpectedFrameCount, frame_count);
330 // Make sure all the frames in the dialog has access to the PDF plugin.
331 preview_dialog->ForEachFrame(base::Bind(&CheckPdfPluginForRenderFrame));