Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / printing / print_preview_dialog_controller_browsertest.cc
blobfbf356a34eff9c9a2e777f118c47d7c1f1f35008
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/memory/scoped_ptr.h"
7 #include "base/run_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
10 #include "chrome/browser/plugins/plugin_prefs.h"
11 #include "chrome/browser/printing/print_preview_dialog_controller.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_commands.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/common/chrome_content_client.h"
16 #include "chrome/common/url_constants.h"
17 #include "chrome/test/base/in_process_browser_test.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "components/printing/common/print_messages.h"
20 #include "content/public/browser/plugin_service.h"
21 #include "content/public/browser/render_frame_host.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/web_contents_observer.h"
24 #include "content/public/test/browser_test_utils.h"
25 #include "ipc/ipc_message_macros.h"
26 #include "url/gurl.h"
28 using content::WebContents;
29 using content::WebContentsObserver;
31 namespace {
33 class RequestPrintPreviewObserver : public WebContentsObserver {
34 public:
35 explicit RequestPrintPreviewObserver(WebContents* dialog)
36 : WebContentsObserver(dialog) {
38 ~RequestPrintPreviewObserver() override {}
40 void set_quit_closure(const base::Closure& quit_closure) {
41 quit_closure_ = quit_closure;
44 private:
45 // content::WebContentsObserver implementation.
46 bool OnMessageReceived(const IPC::Message& message) override {
47 IPC_BEGIN_MESSAGE_MAP(RequestPrintPreviewObserver, message)
48 IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
49 OnRequestPrintPreview)
50 IPC_MESSAGE_UNHANDLED(break;)
51 IPC_END_MESSAGE_MAP();
52 return false; // Report not handled so the real handler receives it.
55 void OnRequestPrintPreview(
56 const PrintHostMsg_RequestPrintPreview_Params& /* params */) {
57 base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure_);
60 base::Closure quit_closure_;
62 DISALLOW_COPY_AND_ASSIGN(RequestPrintPreviewObserver);
65 class PrintPreviewDialogClonedObserver : public WebContentsObserver {
66 public:
67 explicit PrintPreviewDialogClonedObserver(WebContents* dialog)
68 : WebContentsObserver(dialog) {
70 ~PrintPreviewDialogClonedObserver() override {}
72 RequestPrintPreviewObserver* request_preview_dialog_observer() {
73 return request_preview_dialog_observer_.get();
76 private:
77 // content::WebContentsObserver implementation.
78 void DidCloneToNewWebContents(WebContents* old_web_contents,
79 WebContents* new_web_contents) override {
80 request_preview_dialog_observer_.reset(
81 new RequestPrintPreviewObserver(new_web_contents));
84 scoped_ptr<RequestPrintPreviewObserver> request_preview_dialog_observer_;
86 DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogClonedObserver);
89 class PrintPreviewDialogDestroyedObserver : public WebContentsObserver {
90 public:
91 explicit PrintPreviewDialogDestroyedObserver(WebContents* dialog)
92 : WebContentsObserver(dialog),
93 dialog_destroyed_(false) {
95 ~PrintPreviewDialogDestroyedObserver() override {}
97 bool dialog_destroyed() const { return dialog_destroyed_; }
99 private:
100 // content::WebContentsObserver implementation.
101 void WebContentsDestroyed() override { dialog_destroyed_ = true; }
103 bool dialog_destroyed_;
105 DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogDestroyedObserver);
108 void PluginsLoadedCallback(
109 const base::Closure& quit_closure,
110 const std::vector<content::WebPluginInfo>& /* info */) {
111 quit_closure.Run();
114 bool GetPdfPluginInfo(content::WebPluginInfo* info) {
115 base::FilePath pdf_plugin_path = base::FilePath::FromUTF8Unsafe(
116 ChromeContentClient::kPDFPluginPath);
117 return content::PluginService::GetInstance()->GetPluginInfoByPath(
118 pdf_plugin_path, info);
121 const char kDummyPrintUrl[] = "chrome://print/dummy.pdf";
123 void CountFrames(int* frame_count,
124 content::RenderFrameHost* frame) {
125 ++(*frame_count);
128 void CheckPdfPluginForRenderFrame(content::RenderFrameHost* frame) {
129 content::WebPluginInfo pdf_plugin_info;
130 ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));
132 ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
133 EXPECT_TRUE(filter->IsPluginAvailable(
134 frame->GetProcess()->GetID(),
135 frame->GetRoutingID(),
136 nullptr,
137 GURL(kDummyPrintUrl),
138 GURL(),
139 &pdf_plugin_info));
142 } // namespace
144 class PrintPreviewDialogControllerBrowserTest : public InProcessBrowserTest {
145 public:
146 PrintPreviewDialogControllerBrowserTest() : initiator_(NULL) {}
147 ~PrintPreviewDialogControllerBrowserTest() override {}
149 WebContents* initiator() {
150 return initiator_;
153 void PrintPreview() {
154 base::RunLoop run_loop;
155 request_preview_dialog_observer()->set_quit_closure(run_loop.QuitClosure());
156 chrome::Print(browser());
157 run_loop.Run();
160 WebContents* GetPrintPreviewDialog() {
161 printing::PrintPreviewDialogController* dialog_controller =
162 printing::PrintPreviewDialogController::GetInstance();
163 return dialog_controller->GetPrintPreviewForContents(initiator_);
166 private:
167 void SetUpOnMainThread() override {
168 WebContents* first_tab =
169 browser()->tab_strip_model()->GetActiveWebContents();
170 ASSERT_TRUE(first_tab);
172 // Open a new tab so |cloned_tab_observer_| can see it first and attach a
173 // RequestPrintPreviewObserver to it before the real
174 // PrintPreviewMessageHandler gets created. Thus enabling
175 // RequestPrintPreviewObserver to get messages first for the purposes of
176 // this test.
177 cloned_tab_observer_.reset(new PrintPreviewDialogClonedObserver(first_tab));
178 chrome::DuplicateTab(browser());
180 initiator_ = browser()->tab_strip_model()->GetActiveWebContents();
181 ASSERT_TRUE(initiator_);
182 ASSERT_NE(first_tab, initiator_);
184 content::PluginService::GetInstance()->Init();
185 content::PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
188 void TearDownOnMainThread() override {
189 cloned_tab_observer_.reset();
190 initiator_ = NULL;
193 RequestPrintPreviewObserver* request_preview_dialog_observer() {
194 return cloned_tab_observer_->request_preview_dialog_observer();
197 scoped_ptr<PrintPreviewDialogClonedObserver> cloned_tab_observer_;
198 WebContents* initiator_;
200 DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogControllerBrowserTest);
203 // Test to verify that when a initiator navigates, we can create a new preview
204 // dialog for the new tab contents.
205 // http://crbug.com/377337
206 #if defined(OS_WIN)
207 #define MAYBE_NavigateFromInitiatorTab DISABLED_NavigateFromInitiatorTab
208 #else
209 #define MAYBE_NavigateFromInitiatorTab NavigateFromInitiatorTab
210 #endif
211 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
212 MAYBE_NavigateFromInitiatorTab) {
213 // Print for the first time.
214 PrintPreview();
216 // Get the preview dialog for the initiator tab.
217 WebContents* preview_dialog = GetPrintPreviewDialog();
219 // Check a new print preview dialog got created.
220 ASSERT_TRUE(preview_dialog);
221 ASSERT_NE(initiator(), preview_dialog);
223 // Navigate in the initiator tab. Make sure navigating destroys the print
224 // preview dialog.
225 PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
226 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
227 ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());
229 // Try printing again.
230 PrintPreview();
232 // Get the print preview dialog for the initiator tab.
233 WebContents* new_preview_dialog = GetPrintPreviewDialog();
235 // Check a new preview dialog got created.
236 EXPECT_TRUE(new_preview_dialog);
239 // Test to verify that after reloading the initiator, it creates a new print
240 // preview dialog.
241 // http://crbug.com/377337
242 #if defined(OS_WIN)
243 #define MAYBE_ReloadInitiatorTab DISABLED_ReloadInitiatorTab
244 #else
245 #define MAYBE_ReloadInitiatorTab ReloadInitiatorTab
246 #endif
247 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
248 MAYBE_ReloadInitiatorTab) {
249 // Print for the first time.
250 PrintPreview();
252 WebContents* preview_dialog = GetPrintPreviewDialog();
254 // Check a new print preview dialog got created.
255 ASSERT_TRUE(preview_dialog);
256 ASSERT_NE(initiator(), preview_dialog);
258 // Reload the initiator. Make sure reloading destroys the print preview
259 // dialog.
260 PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
261 chrome::Reload(browser(), CURRENT_TAB);
262 content::WaitForLoadStop(
263 browser()->tab_strip_model()->GetActiveWebContents());
264 ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());
266 // Try printing again.
267 PrintPreview();
269 // Create a preview dialog for the initiator tab.
270 WebContents* new_preview_dialog = GetPrintPreviewDialog();
271 EXPECT_TRUE(new_preview_dialog);
274 // Test to verify that after print preview works even when the PDF plugin is
275 // disabled for webpages.
276 IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
277 PdfPluginDisabled) {
278 // Make sure plugins are loaded.
280 base::RunLoop run_loop;
281 content::PluginService::GetInstance()->GetPlugins(
282 base::Bind(&PluginsLoadedCallback, run_loop.QuitClosure()));
283 run_loop.Run();
285 // Get the PDF plugin info.
286 content::WebPluginInfo pdf_plugin_info;
287 ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));
289 // Disable the PDF plugin.
290 PluginPrefs::GetForProfile(browser()->profile())->EnablePluginGroup(
291 false, base::ASCIIToUTF16(ChromeContentClient::kPDFPluginName));
293 // Make sure it is actually disabled for webpages.
294 ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
295 content::WebPluginInfo dummy_pdf_plugin_info = pdf_plugin_info;
296 EXPECT_FALSE(filter->IsPluginAvailable(
297 initiator()->GetRenderProcessHost()->GetID(),
298 initiator()->GetMainFrame()->GetRoutingID(),
299 nullptr,
300 GURL("http://google.com"),
301 GURL(),
302 &dummy_pdf_plugin_info));
304 PrintPreview();
306 // Check a new print preview dialog got created.
307 WebContents* preview_dialog = GetPrintPreviewDialog();
308 ASSERT_TRUE(preview_dialog);
309 ASSERT_NE(initiator(), preview_dialog);
311 // Wait until the <iframe> in the print preview renderer has loaded.
312 // |frame_count| should be 2. The other frame is the main frame.
313 const int kExpectedFrameCount = 2;
314 int frame_count;
315 do {
316 base::RunLoop run_loop;
317 base::MessageLoop::current()->PostDelayedTask(
318 FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(1));
319 run_loop.Run();
321 frame_count = 0;
322 preview_dialog->ForEachFrame(
323 base::Bind(&CountFrames, base::Unretained(&frame_count)));
324 } while (frame_count < kExpectedFrameCount);
325 ASSERT_EQ(kExpectedFrameCount, frame_count);
327 // Make sure all the frames in the dialog has access to the PDF plugin.
328 preview_dialog->ForEachFrame(base::Bind(&CheckPdfPluginForRenderFrame));