1 // Copyright 2013 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/strings/stringprintf.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "base/win/windows_version.h"
8 #include "chrome/browser/apps/app_browsertest_util.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/extension_test_message_listener.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/test/base/ui_test_utils.h"
14 #include "content/public/common/page_transition_types.h"
15 #include "content/public/test/browser_test_base.h"
16 #include "content/public/test/browser_test_utils.h"
17 #include "net/test/embedded_test_server/embedded_test_server.h"
19 namespace extensions {
21 class PlatformAppUrlRedirectorBrowserTest : public PlatformAppBrowserTest {
23 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
26 // Performs the following sequence:
27 // - installs the app |handler| (a relative path under the platform_apps
29 // - navigates the current tab to the HTML page |lancher_page| (ditto);
30 // - then waits for |handler| to launch and send back a |handler_ack_message|;
31 // - finally checks that the resulting app window count is as expected.
32 // The |launcher_page| is supposed to trigger a navigation matching one of the
33 // url_handlers in the |handler|'s manifest, and thereby launch the |handler|.
34 void TestNavigationInTab(const char* launcher_page,
36 const char* handler_start_message);
38 // The same as above, but does not expect the |handler| to launch. Verifies
39 // that it didn't, and that the navigation has opened in a new tab instead.
40 void TestMismatchingNavigationInTab(const char* launcher_page,
41 const char* success_tab_title,
44 // - installs the app |handler|;
45 // - opens the page |xhr_opening_page| in the current tab;
46 // - the page sends an XHR to a local resouce, whose URL matches one of the
47 // url_handlers in |handler|;
48 // - waits until |xhr_opening_page| gets a response back and changes the tab's
49 // title to a value indicating success/failure of the XHR;
50 // - verifies that no app windows have been opened, i.e. |handler| wasn't
51 // launched even though its url_handlers match the URL.
52 void TestNegativeXhrInTab(const char* xhr_opening_page,
53 const char* success_tab_title,
54 const char* failure_tab_title,
57 // Performs the following sequence:
58 // - installs the app |handler| (a relative path under the platform_apps
60 // - loads and launches the app |launcher| (ditto);
61 // - waits for the |launcher| to launch and send back a |launcher_ack_message|
62 // (to make sure it's not the failing entity, if the test fails overall);
63 // - waits for the |handler| to launch and send back a |handler_ack_message|;
64 // - finally checks that the resulting app window count is as expected.
65 // The |launcher| is supposed to trigger a navigation matching one of the
66 // url_handlers in the |handler|'s manifest, and thereby launch the |handler|.
67 void TestNavigationInApp(const char* launcher,
68 const char* launcher_done_message,
70 const char* handler_start_message);
72 // The same as above, but does not expect the |handler| to launch. Verifies
73 // that it didn't, and that the navigation has opened in a new tab instead.
74 void TestMismatchingNavigationInApp(const char* launcher,
75 const char* launcher_done_message,
78 // - installs the |handler| app;
79 // - loads and launches the |launcher| app;
80 // - waits until the |launcher| sends back a |launcher_done_message|;
81 // - the launcher performs a navigation to a URL that mismatches the
82 // |handler|'s url_handlers;
83 // - verifies that the |handler| hasn't been launched as a result of the
85 void TestNegativeNavigationInApp(const char* launcher,
86 const char* launcher_done_message,
89 // - installs the app |handler|;
90 // - navigates the current tab to the HTML page |matching_target_page| with
91 // page transition |transition|;
92 // - waits for |handler| to launch and send back a |handler_start_message|;
93 // - finally checks that the resulting app window count is as expected.
94 void TestNavigationInBrowser(const char* matching_target_page,
95 content::PageTransition transition,
97 const char* handler_start_message);
99 // Same as above, but does not expect |handler| to launch. This is used, e.g.
100 // for form submissions, where the URL would normally match the url_handlers
101 // but should not launch it.
102 void TestNegativeNavigationInBrowser(const char* matching_target_page,
103 content::PageTransition transition,
104 const char* success_tab_title,
105 const char* handler);
107 // Same as above, but expects the |mismatching_target_page| should not match
108 // any of the |handler|'s url_handlers, and therefor not launch the app.
109 void TestMismatchingNavigationInBrowser(const char* mismatching_target_page,
110 content::PageTransition transition,
111 const char* success_tab_title,
112 const char* handler);
116 void PlatformAppUrlRedirectorBrowserTest::SetUpCommandLine(
117 CommandLine* command_line) {
118 PlatformAppBrowserTest::SetUpCommandLine(command_line);
119 command_line->AppendSwitch(::switches::kDisablePopupBlocking);
122 // TODO(sergeygs): Factor out common functionality from TestXyz,
123 // TestNegativeXyz, and TestMismatchingXyz versions.
125 // TODO(sergeys): Return testing::AssertionErrors from these methods to
126 // preserve line numbers and (if applicable) failure messages.
128 void PlatformAppUrlRedirectorBrowserTest::TestNavigationInTab(
129 const char* launcher_page,
131 const char* handler_start_message) {
132 ASSERT_TRUE(StartEmbeddedTestServer());
134 InstallPlatformApp(handler);
136 ExtensionTestMessageListener handler_listener(handler_start_message, false);
138 ui_test_utils::NavigateToURLWithDisposition(
140 embedded_test_server()->GetURL(base::StringPrintf(
141 "/extensions/platform_apps/%s", launcher_page)),
143 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
145 ASSERT_TRUE(handler_listener.WaitUntilSatisfied());
147 ASSERT_EQ(1U, GetAppWindowCount());
150 void PlatformAppUrlRedirectorBrowserTest::TestMismatchingNavigationInTab(
151 const char* launcher_page,
152 const char* success_tab_title,
153 const char* handler) {
154 ASSERT_TRUE(StartEmbeddedTestServer());
156 InstallPlatformApp(handler);
158 const base::string16 success_title = base::ASCIIToUTF16(success_tab_title);
159 content::WebContents* tab =
160 browser()->tab_strip_model()->GetActiveWebContents();
161 content::TitleWatcher title_watcher(tab, success_title);
163 ui_test_utils::NavigateToURLWithDisposition(
165 embedded_test_server()->GetURL(base::StringPrintf(
166 "/extensions/platform_apps/%s", launcher_page)),
168 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
170 ASSERT_EQ(success_title, title_watcher.WaitAndGetTitle());
171 ASSERT_EQ(1, browser()->tab_strip_model()->count());
172 ASSERT_EQ(0U, GetAppWindowCount());
175 void PlatformAppUrlRedirectorBrowserTest::TestNegativeXhrInTab(
176 const char* launcher_page,
177 const char* success_tab_title,
178 const char* failure_tab_title,
179 const char* handler) {
180 ASSERT_TRUE(StartEmbeddedTestServer());
182 InstallPlatformApp(handler);
184 const base::string16 success_title = base::ASCIIToUTF16(success_tab_title);
185 const base::string16 failure_title = base::ASCIIToUTF16(failure_tab_title);
186 content::WebContents* tab =
187 browser()->tab_strip_model()->GetActiveWebContents();
188 content::TitleWatcher title_watcher(tab, success_title);
189 title_watcher.AlsoWaitForTitle(failure_title);
191 ui_test_utils::NavigateToURLWithDisposition(
193 embedded_test_server()->GetURL(base::StringPrintf(
194 "/extensions/platform_apps/%s", launcher_page)),
196 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
198 ASSERT_EQ(success_title, title_watcher.WaitAndGetTitle());
199 ASSERT_EQ(1, browser()->tab_strip_model()->count());
200 ASSERT_EQ(0U, GetAppWindowCount());
203 void PlatformAppUrlRedirectorBrowserTest::TestNavigationInApp(
204 const char* launcher,
205 const char* launcher_done_message,
207 const char* handler_start_message) {
208 ASSERT_TRUE(StartEmbeddedTestServer());
210 InstallPlatformApp(handler);
212 ExtensionTestMessageListener launcher_listener(launcher_done_message, false);
213 ExtensionTestMessageListener handler_listener(handler_start_message, false);
215 LoadAndLaunchPlatformApp(launcher);
217 ASSERT_TRUE(launcher_listener.WaitUntilSatisfied());
218 ASSERT_TRUE(handler_listener.WaitUntilSatisfied());
220 ASSERT_EQ(2U, GetAppWindowCount());
223 void PlatformAppUrlRedirectorBrowserTest::TestNegativeNavigationInApp(
224 const char* launcher,
225 const char* launcher_done_message,
226 const char* handler) {
227 ASSERT_TRUE(StartEmbeddedTestServer());
229 InstallPlatformApp(handler);
231 content::WindowedNotificationObserver observer(
232 chrome::NOTIFICATION_TAB_ADDED,
233 content::Source<content::WebContentsDelegate>(browser()));
235 ExtensionTestMessageListener launcher_done_listener(launcher_done_message,
237 LoadAndLaunchPlatformApp(launcher);
239 ASSERT_TRUE(launcher_done_listener.WaitUntilSatisfied());
243 ASSERT_EQ(1U, GetAppWindowCount());
246 void PlatformAppUrlRedirectorBrowserTest::TestMismatchingNavigationInApp(
247 const char* launcher,
248 const char* launcher_done_message,
249 const char* handler) {
250 ASSERT_TRUE(StartEmbeddedTestServer());
252 InstallPlatformApp(handler);
254 content::WindowedNotificationObserver observer(
255 chrome::NOTIFICATION_TAB_ADDED,
256 content::Source<content::WebContentsDelegate>(browser()));
258 ExtensionTestMessageListener launcher_listener(launcher_done_message, false);
259 LoadAndLaunchPlatformApp(launcher);
261 ASSERT_TRUE(launcher_listener.WaitUntilSatisfied());
264 ASSERT_EQ(1U, GetAppWindowCount());
265 ASSERT_EQ(2, browser()->tab_strip_model()->count());
268 void PlatformAppUrlRedirectorBrowserTest::TestNavigationInBrowser(
269 const char* matching_target_page,
270 content::PageTransition transition,
272 const char* handler_start_message) {
273 ASSERT_TRUE(StartEmbeddedTestServer());
275 InstallPlatformApp(handler);
277 ExtensionTestMessageListener handler_listener(handler_start_message, false);
279 chrome::NavigateParams params(
281 embedded_test_server()->GetURL(base::StringPrintf(
282 "/extensions/platform_apps/%s", matching_target_page)),
284 ui_test_utils::NavigateToURL(¶ms);
286 ASSERT_TRUE(handler_listener.WaitUntilSatisfied());
288 ASSERT_EQ(1U, GetAppWindowCount());
291 void PlatformAppUrlRedirectorBrowserTest::TestNegativeNavigationInBrowser(
292 const char* matching_target_page,
293 content::PageTransition transition,
294 const char* success_tab_title,
295 const char* handler) {
296 ASSERT_TRUE(StartEmbeddedTestServer());
298 InstallPlatformApp(handler);
300 const base::string16 success_title = base::ASCIIToUTF16(success_tab_title);
301 content::WebContents* tab =
302 browser()->tab_strip_model()->GetActiveWebContents();
303 content::TitleWatcher title_watcher(tab, success_title);
305 chrome::NavigateParams params(
307 embedded_test_server()->GetURL(base::StringPrintf(
308 "/extensions/platform_apps/%s", matching_target_page)),
310 ui_test_utils::NavigateToURL(¶ms);
312 ASSERT_EQ(success_title, title_watcher.WaitAndGetTitle());
313 ASSERT_EQ(0U, GetAppWindowCount());
316 void PlatformAppUrlRedirectorBrowserTest::TestMismatchingNavigationInBrowser(
317 const char* mismatching_target_page,
318 content::PageTransition transition,
319 const char* success_tab_title,
320 const char* handler) {
321 TestNegativeNavigationInBrowser(
322 mismatching_target_page, transition, success_tab_title, handler);
325 // Test that a click on a regular link in a tab launches an app that has
326 // matching url_handlers.
327 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
328 ClickInTabIntercepted) {
330 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
333 "url_handlers/launching_pages/click_link.html",
334 "url_handlers/handlers/simple",
338 // Test that a click on a target='_blank' link in a tab launches an app that has
339 // matching url_handlers.
340 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
341 BlankClickInTabIntercepted) {
343 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
346 "url_handlers/launching_pages/click_blank_link.html",
347 "url_handlers/handlers/simple",
351 // Test that a call to window.open() in a tab launches an app that has
352 // matching url_handlers.
353 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
354 WindowOpenInTabIntercepted) {
356 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
359 "url_handlers/launching_pages/call_window_open.html",
360 "url_handlers/handlers/simple",
364 // Test that a click on a regular link in a tab launches an app that has
365 // matching url_handlers.
366 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
367 MismatchingClickInTabNotIntercepted) {
369 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
371 TestMismatchingNavigationInTab(
372 "url_handlers/launching_pages/click_mismatching_link.html",
373 "Mismatching link target loaded",
374 "url_handlers/handlers/simple");
377 // Test that a click on target='_blank' link in an app's window launches
378 // another app that has matching url_handlers.
379 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
380 BlankClickInAppIntercepted) {
382 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
385 "url_handlers/launchers/click_blank_link",
387 "url_handlers/handlers/simple",
391 // Test that a call to window.open() in the app's foreground page launches
392 // another app that has matching url_handlers.
393 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
394 WindowOpenInAppIntercepted) {
396 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
399 "url_handlers/launchers/call_window_open",
401 "url_handlers/handlers/simple",
405 // Test that an app with url_handlers does not intercept a mismatching
406 // click on a target='_blank' link in another app's window.
407 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
408 MismatchingWindowOpenInAppNotIntercepted) {
410 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
412 TestMismatchingNavigationInApp(
413 "url_handlers/launchers/call_mismatching_window_open",
415 "url_handlers/handlers/simple");
418 // Test that a webview in an app can be navigated to a URL without interception
419 // even when there are other (or the same) apps that have matching url_handlers.
420 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
421 WebviewNavigationNotIntercepted) {
423 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
425 // The launcher clicks on a link, which gets intercepted and launches the
426 // handler. The handler also redirects an embedded webview to the URL. The
427 // webview should just navigate without creating an endless loop of
428 // navigate-intercept-launch sequences with multiplying handler's windows.
429 // There should be 2 windows only: launcher's and handler's.
431 "url_handlers/launchers/click_blank_link",
433 "url_handlers/handlers/navigate_webview_to_url",
437 // Test that a webview in an app can be navigated to a URL without interception
438 // even when there are other (or the same) apps that have matching url_handlers.
439 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
440 MismatchingBlankClickInAppNotIntercepted) {
442 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
444 // The launcher clicks on a link, which gets intercepted and launches the
445 // handler. The handler also redirects an embedded webview to the URL. The
446 // webview should just navigate without creating an endless loop of
447 // navigate-intercept-launch sequences with multiplying handler's windows.
448 // There should be 2 windows only: launcher's and handler's.
449 TestMismatchingNavigationInApp(
450 "url_handlers/launchers/click_mismatching_blank_link",
452 "url_handlers/handlers/simple");
455 // Test that a URL entry in the omnibar launches an app that has matching
457 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
458 EntryInOmnibarIntercepted) {
460 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
462 TestNavigationInBrowser(
463 "url_handlers/common/target.html",
464 content::PAGE_TRANSITION_TYPED,
465 "url_handlers/handlers/simple",
469 // Test that an app with url_handlers does not intercept a mismatching
470 // URL entry in the omnibar.
471 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
472 MismatchingEntryInOmnibarNotIntercepted) {
474 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
476 TestMismatchingNavigationInBrowser(
477 "url_handlers/common/mismatching_target.html",
478 content::PAGE_TRANSITION_TYPED,
479 "Mismatching link target loaded",
480 "url_handlers/handlers/simple");
483 // Test that a form submission in a page is never subject to interception
484 // by apps even with matching url_handlers.
485 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
486 FormSubmissionInTabNotIntercepted) {
488 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
490 TestMismatchingNavigationInTab(
491 "url_handlers/launching_pages/submit_form.html",
492 "Link target loaded",
493 "url_handlers/handlers/simple");
496 // Test that a form submission in a page is never subject to interception
497 // by apps even with matching url_handlers.
498 IN_PROC_BROWSER_TEST_F(PlatformAppUrlRedirectorBrowserTest,
499 XhrInTabNotIntercepted) {
501 if (base::win::GetVersion() < base::win::VERSION_VISTA) return; // Bug 301638
503 TestNegativeXhrInTab(
504 "url_handlers/xhr_downloader/main.html",
507 "url_handlers/handlers/steal_xhr_target");
510 } // namespace extensions