Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / window_open_apitest.cc
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.
4
5 #include "base/command_line.h"
6 #include "base/memory/scoped_vector.h"
7 #include "base/path_service.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/extensions/extension_apitest.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_finder.h"
13 #include "chrome/browser/ui/browser_iterator.h"
14 #include "chrome/browser/ui/panels/panel_manager.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/test/base/test_switches.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/common/result_codes.h"
23 #include "content/public/common/url_constants.h"
24 #include "content/public/test/browser_test_utils.h"
25 #include "extensions/browser/extension_host.h"
26 #include "extensions/browser/extension_system.h"
27 #include "extensions/browser/process_manager.h"
28 #include "extensions/common/constants.h"
29 #include "extensions/common/extension.h"
30 #include "extensions/common/switches.h"
31 #include "extensions/test/extension_test_message_listener.h"
32 #include "extensions/test/result_catcher.h"
33 #include "net/dns/mock_host_resolver.h"
34 #include "net/test/embedded_test_server/embedded_test_server.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36
37 #if defined(USE_ASH)
38 #include "extensions/browser/app_window/app_window_registry.h"
39 #endif
40
41 #if defined(USE_ASH) && defined(OS_CHROMEOS)
42 // TODO(stevenjb): Figure out the correct behavior for Ash + Win
43 #define USE_ASH_PANELS
44 #endif
45
46 using content::OpenURLParams;
47 using content::Referrer;
48 using content::WebContents;
49
50 // Disabled, http://crbug.com/64899.
51 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_WindowOpen) {
52   CommandLine::ForCurrentProcess()->AppendSwitch(
53       extensions::switches::kEnableExperimentalExtensionApis);
54
55   extensions::ResultCatcher catcher;
56   ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
57       .AppendASCII("window_open").AppendASCII("spanning")));
58   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
59 }
60
61 int GetPanelCount(Browser* browser) {
62 #if defined(USE_ASH_PANELS)
63   return static_cast<int>(extensions::AppWindowRegistry::Get(
64       browser->profile())->app_windows().size());
65 #else
66   return PanelManager::GetInstance()->num_panels();
67 #endif
68 }
69
70 bool WaitForTabsAndPopups(Browser* browser,
71                           int num_tabs,
72                           int num_popups,
73                           int num_panels) {
74   SCOPED_TRACE(
75       base::StringPrintf("WaitForTabsAndPopups tabs:%d, popups:%d, panels:%d",
76                          num_tabs, num_popups, num_panels));
77   // We start with one tab and one browser already open.
78   ++num_tabs;
79   size_t num_browsers = static_cast<size_t>(num_popups) + 1;
80
81   const base::TimeDelta kWaitTime = base::TimeDelta::FromSeconds(10);
82   base::TimeTicks end_time = base::TimeTicks::Now() + kWaitTime;
83   while (base::TimeTicks::Now() < end_time) {
84     if (chrome::GetBrowserCount(browser->profile(),
85                                 browser->host_desktop_type()) == num_browsers &&
86         browser->tab_strip_model()->count() == num_tabs &&
87         GetPanelCount(browser) == num_panels)
88       break;
89
90     content::RunAllPendingInMessageLoop();
91   }
92
93   EXPECT_EQ(num_browsers,
94             chrome::GetBrowserCount(browser->profile(),
95                                     browser->host_desktop_type()));
96   EXPECT_EQ(num_tabs, browser->tab_strip_model()->count());
97   EXPECT_EQ(num_panels, GetPanelCount(browser));
98
99   int num_popups_seen = 0;
100   for (chrome::BrowserIterator iter; !iter.done(); iter.Next()) {
101     if (*iter == browser)
102       continue;
103
104     EXPECT_TRUE((*iter)->is_type_popup());
105     ++num_popups_seen;
106   }
107   EXPECT_EQ(num_popups, num_popups_seen);
108
109   return ((num_browsers ==
110                chrome::GetBrowserCount(browser->profile(),
111                                        browser->host_desktop_type())) &&
112           (num_tabs == browser->tab_strip_model()->count()) &&
113           (num_panels == GetPanelCount(browser)) &&
114           (num_popups == num_popups_seen));
115 }
116
117 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, BrowserIsApp) {
118   host_resolver()->AddRule("a.com", "127.0.0.1");
119   ASSERT_TRUE(StartEmbeddedTestServer());
120   ASSERT_TRUE(LoadExtension(
121       test_data_dir_.AppendASCII("window_open").AppendASCII("browser_is_app")));
122
123   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 0, 2, 0));
124
125   for (chrome::BrowserIterator iter; !iter.done(); iter.Next()) {
126     if (*iter == browser())
127       ASSERT_FALSE(iter->is_app());
128     else
129       ASSERT_TRUE(iter->is_app());
130   }
131 }
132
133 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowOpenPopupDefault) {
134   ASSERT_TRUE(StartEmbeddedTestServer());
135   ASSERT_TRUE(LoadExtension(
136       test_data_dir_.AppendASCII("window_open").AppendASCII("popup")));
137
138   const int num_tabs = 1;
139   const int num_popups = 0;
140   EXPECT_TRUE(WaitForTabsAndPopups(browser(), num_tabs, num_popups, 0));
141 }
142
143 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowOpenPopupIframe) {
144   ASSERT_TRUE(StartEmbeddedTestServer());
145   base::FilePath test_data_dir;
146   PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
147   embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
148   ASSERT_TRUE(LoadExtension(
149       test_data_dir_.AppendASCII("window_open").AppendASCII("popup_iframe")));
150
151   const int num_tabs = 1;
152   const int num_popups = 0;
153   EXPECT_TRUE(WaitForTabsAndPopups(browser(), num_tabs, num_popups, 0));
154 }
155
156 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowOpenPopupLarge) {
157   ASSERT_TRUE(StartEmbeddedTestServer());
158   ASSERT_TRUE(LoadExtension(
159       test_data_dir_.AppendASCII("window_open").AppendASCII("popup_large")));
160
161   // On other systems this should open a new popup window.
162   const int num_tabs = 0;
163   const int num_popups = 1;
164   EXPECT_TRUE(WaitForTabsAndPopups(browser(), num_tabs, num_popups, 0));
165 }
166
167 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowOpenPopupSmall) {
168   ASSERT_TRUE(StartEmbeddedTestServer());
169   ASSERT_TRUE(LoadExtension(
170       test_data_dir_.AppendASCII("window_open").AppendASCII("popup_small")));
171
172   // On ChromeOS this should open a new panel (acts like a new popup window).
173   // On other systems this should open a new popup window.
174   const int num_tabs = 0;
175   const int num_popups = 1;
176   EXPECT_TRUE(WaitForTabsAndPopups(browser(), num_tabs, num_popups, 0));
177 }
178
179 // Disabled on Windows. Often times out or fails: crbug.com/177530
180 #if defined(OS_WIN)
181 #define MAYBE_PopupBlockingExtension DISABLED_PopupBlockingExtension
182 #else
183 #define MAYBE_PopupBlockingExtension PopupBlockingExtension
184 #endif
185 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_PopupBlockingExtension) {
186   host_resolver()->AddRule("*", "127.0.0.1");
187   ASSERT_TRUE(StartEmbeddedTestServer());
188
189   ASSERT_TRUE(LoadExtension(
190       test_data_dir_.AppendASCII("window_open").AppendASCII("popup_blocking")
191       .AppendASCII("extension")));
192
193   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 5, 3, 0));
194 }
195
196 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, PopupBlockingHostedApp) {
197   host_resolver()->AddRule("*", "127.0.0.1");
198   ASSERT_TRUE(test_server()->Start());
199
200   ASSERT_TRUE(LoadExtension(
201       test_data_dir_.AppendASCII("window_open").AppendASCII("popup_blocking")
202       .AppendASCII("hosted_app")));
203
204   // The app being tested owns the domain a.com .  The test URLs we navigate
205   // to below must be within that domain, so that they fall within the app's
206   // web extent.
207   GURL::Replacements replace_host;
208   std::string a_dot_com = "a.com";
209   replace_host.SetHostStr(a_dot_com);
210
211   const std::string popup_app_contents_path(
212     "files/extensions/api_test/window_open/popup_blocking/hosted_app/");
213
214   GURL open_tab =
215       test_server()->GetURL(popup_app_contents_path + "open_tab.html")
216           .ReplaceComponents(replace_host);
217   GURL open_popup =
218       test_server()->GetURL(popup_app_contents_path + "open_popup.html")
219           .ReplaceComponents(replace_host);
220
221   browser()->OpenURL(OpenURLParams(
222       open_tab, Referrer(), NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED,
223       false));
224   browser()->OpenURL(OpenURLParams(
225       open_popup, Referrer(), NEW_FOREGROUND_TAB,
226       ui::PAGE_TRANSITION_TYPED, false));
227
228   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 3, 1, 0));
229 }
230
231 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WindowArgumentsOverflow) {
232   ASSERT_TRUE(RunExtensionTest("window_open/argument_overflow")) << message_;
233 }
234
235 class WindowOpenPanelDisabledTest : public ExtensionApiTest {
236   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
237     ExtensionApiTest::SetUpCommandLine(command_line);
238     // TODO(jennb): Re-enable when panels are enabled by default.
239     // command_line->AppendSwitch(switches::kDisablePanels);
240   }
241 };
242
243 IN_PROC_BROWSER_TEST_F(WindowOpenPanelDisabledTest,
244                        DISABLED_WindowOpenPanelNotEnabled) {
245   ASSERT_TRUE(RunExtensionTest("window_open/panel_not_enabled")) << message_;
246 }
247
248 class WindowOpenPanelTest : public ExtensionApiTest {
249   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
250     ExtensionApiTest::SetUpCommandLine(command_line);
251     command_line->AppendSwitch(switches::kEnablePanels);
252   }
253 };
254
255 #if defined(USE_ASH_PANELS)
256 // On Ash, this currently fails because we're currently opening new panel
257 // windows as popup windows instead.
258 #define MAYBE_WindowOpenPanel DISABLED_WindowOpenPanel
259 #else
260 #define MAYBE_WindowOpenPanel WindowOpenPanel
261 #endif
262 IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, MAYBE_WindowOpenPanel) {
263   ASSERT_TRUE(RunExtensionTest("window_open/panel")) << message_;
264 }
265
266 #if defined(USE_ASH_PANELS) || defined(OS_LINUX)
267 // On Ash, this currently fails because we're currently opening new panel
268 // windows as popup windows instead.
269 // We're also failing on Linux-aura due to the panel is not opened in the
270 // right origin.
271 #define MAYBE_WindowOpenPanelDetached DISABLED_WindowOpenPanelDetached
272 #else
273 #define MAYBE_WindowOpenPanelDetached WindowOpenPanelDetached
274 #endif
275 IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, MAYBE_WindowOpenPanelDetached) {
276   ASSERT_TRUE(RunExtensionTest("window_open/panel_detached")) << message_;
277 }
278
279 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
280 // TODO(erg): Bring up ash http://crbug.com/300084
281 #define MAYBE_CloseNonExtensionPanelsOnUninstall \
282   DISABLED_CloseNonExtensionPanelsOnUninstall
283 #else
284 #define MAYBE_CloseNonExtensionPanelsOnUninstall \
285   CloseNonExtensionPanelsOnUninstall
286 #endif
287 IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest,
288                        MAYBE_CloseNonExtensionPanelsOnUninstall) {
289 #if defined(OS_WIN) && defined(USE_ASH)
290   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
291   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
292     return;
293 #endif
294
295 #if defined(USE_ASH_PANELS)
296   // On Ash, new panel windows open as popup windows instead.
297   int num_popups, num_panels;
298   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePanels)) {
299     num_popups = 2;
300     num_panels = 2;
301   } else {
302     num_popups = 4;
303     num_panels = 0;
304   }
305 #else
306   int num_popups = 2;
307   int num_panels = 2;
308 #endif
309   ASSERT_TRUE(StartEmbeddedTestServer());
310
311   // Setup listeners to wait on strings we expect the extension pages to send.
312   std::vector<std::string> test_strings;
313   test_strings.push_back("content_tab");
314   if (num_panels)
315     test_strings.push_back("content_panel");
316   test_strings.push_back("content_popup");
317
318   ScopedVector<ExtensionTestMessageListener> listeners;
319   for (size_t i = 0; i < test_strings.size(); ++i) {
320     listeners.push_back(
321         new ExtensionTestMessageListener(test_strings[i], false));
322   }
323
324   const extensions::Extension* extension = LoadExtension(
325       test_data_dir_.AppendASCII("window_open").AppendASCII(
326           "close_panels_on_uninstall"));
327   ASSERT_TRUE(extension);
328
329   // Two tabs. One in extension domain and one in non-extension domain.
330   // Two popups - one in extension domain and one in non-extension domain.
331   // Two panels - one in extension domain and one in non-extension domain.
332   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 2, num_popups, num_panels));
333
334   // Wait on test messages to make sure the pages loaded.
335   for (size_t i = 0; i < listeners.size(); ++i)
336     ASSERT_TRUE(listeners[i]->WaitUntilSatisfied());
337
338   UninstallExtension(extension->id());
339
340   // Wait for the tabs and popups in non-extension domain to stay open.
341   // Expect everything else, including panels, to close.
342   num_popups -= 1;
343 #if defined(USE_ASH_PANELS)
344   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePanels)) {
345     // On Ash, new panel windows open as popup windows instead, so there are 2
346     // extension domain popups that will close (instead of 1 popup on non-Ash).
347     num_popups -= 1;
348   }
349 #endif
350 #if defined(USE_ASH)
351 #if !defined(OS_WIN)
352   // On linux ash we close all popup applications when closing its extension.
353   num_popups = 0;
354 #endif
355 #endif
356   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 1, num_popups, 0));
357 }
358
359 // This test isn't applicable on Chrome OS, which automatically reloads crashed
360 // pages.
361 #if !defined(OS_CHROMEOS)
362 IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, ClosePanelsOnExtensionCrash) {
363 #if defined(USE_ASH_PANELS)
364   // On Ash, new panel windows open as popup windows instead.
365   int num_popups = 4;
366   int num_panels = 0;
367 #else
368   int num_popups = 2;
369   int num_panels = 2;
370 #endif
371   ASSERT_TRUE(StartEmbeddedTestServer());
372
373   // Setup listeners to wait on strings we expect the extension pages to send.
374   std::vector<std::string> test_strings;
375   test_strings.push_back("content_tab");
376   if (num_panels)
377     test_strings.push_back("content_panel");
378   test_strings.push_back("content_popup");
379
380   ScopedVector<ExtensionTestMessageListener> listeners;
381   for (size_t i = 0; i < test_strings.size(); ++i) {
382     listeners.push_back(
383         new ExtensionTestMessageListener(test_strings[i], false));
384   }
385
386   const extensions::Extension* extension = LoadExtension(
387       test_data_dir_.AppendASCII("window_open").AppendASCII(
388           "close_panels_on_uninstall"));
389   ASSERT_TRUE(extension);
390
391   // Two tabs. One in extension domain and one in non-extension domain.
392   // Two popups - one in extension domain and one in non-extension domain.
393   // Two panels - one in extension domain and one in non-extension domain.
394   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 2, num_popups, num_panels));
395
396   // Wait on test messages to make sure the pages loaded.
397   for (size_t i = 0; i < listeners.size(); ++i)
398     ASSERT_TRUE(listeners[i]->WaitUntilSatisfied());
399
400   // Crash the extension.
401   extensions::ExtensionHost* extension_host =
402       extensions::ExtensionSystem::Get(browser()->profile())->
403           process_manager()->GetBackgroundHostForExtension(extension->id());
404   ASSERT_TRUE(extension_host);
405   base::KillProcess(extension_host->render_process_host()->GetHandle(),
406                     content::RESULT_CODE_KILLED, false);
407   WaitForExtensionCrash(extension->id());
408
409   // Only expect panels to close. The rest stay open to show a sad-tab.
410   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 2, num_popups, 0));
411 }
412 #endif  // !defined(OS_CHROMEOS)
413
414 #if defined(USE_ASH_PANELS)
415 // This test is not applicable on Ash. The modified window.open behavior only
416 // applies to non-Ash panel windows.
417 #define MAYBE_WindowOpenFromPanel DISABLED_WindowOpenFromPanel
418 #else
419 #define MAYBE_WindowOpenFromPanel WindowOpenFromPanel
420 #endif
421 IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, MAYBE_WindowOpenFromPanel) {
422   ASSERT_TRUE(StartEmbeddedTestServer());
423
424   // Load the extension that will open a panel which then calls window.open.
425   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("window_open").
426                             AppendASCII("panel_window_open")));
427
428   // Expect one panel (opened by extension) and one tab (from the panel calling
429   // window.open). Panels modify the WindowOpenDisposition in window.open
430   // to always open in a tab.
431   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 1, 0, 1));
432 }
433
434 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_WindowOpener) {
435   ASSERT_TRUE(RunExtensionTest("window_open/opener")) << message_;
436 }
437
438 #if defined(OS_MACOSX)
439 // Extension popup windows are incorrectly sized on OSX, crbug.com/225601
440 #define MAYBE_WindowOpenSized DISABLED_WindowOpenSized
441 #else
442 #define MAYBE_WindowOpenSized WindowOpenSized
443 #endif
444 // Ensure that the width and height properties of a window opened with
445 // chrome.windows.create match the creation parameters. See crbug.com/173831.
446 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_WindowOpenSized) {
447   ASSERT_TRUE(RunExtensionTest("window_open/window_size")) << message_;
448   EXPECT_TRUE(WaitForTabsAndPopups(browser(), 0, 1, 0));
449 }
450
451 // Tests that an extension page can call window.open to an extension URL and
452 // the new window has extension privileges.
453 IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenExtension) {
454   ASSERT_TRUE(LoadExtension(
455       test_data_dir_.AppendASCII("uitest").AppendASCII("window_open")));
456
457   GURL start_url(std::string(extensions::kExtensionScheme) +
458                      url::kStandardSchemeSeparator +
459                      last_loaded_extension_id() + "/test.html");
460   ui_test_utils::NavigateToURL(browser(), start_url);
461   WebContents* newtab = NULL;
462   ASSERT_NO_FATAL_FAILURE(
463       OpenWindow(browser()->tab_strip_model()->GetActiveWebContents(),
464       start_url.Resolve("newtab.html"), true, &newtab));
465
466   bool result = false;
467   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(newtab, "testExtensionApi()",
468                                                    &result));
469   EXPECT_TRUE(result);
470 }
471
472 // Tests that if an extension page calls window.open to an invalid extension
473 // URL, the browser doesn't crash.
474 IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenInvalidExtension) {
475   ASSERT_TRUE(LoadExtension(
476       test_data_dir_.AppendASCII("uitest").AppendASCII("window_open")));
477
478   GURL start_url(std::string(extensions::kExtensionScheme) +
479                      url::kStandardSchemeSeparator +
480                      last_loaded_extension_id() + "/test.html");
481   ui_test_utils::NavigateToURL(browser(), start_url);
482   ASSERT_NO_FATAL_FAILURE(
483       OpenWindow(browser()->tab_strip_model()->GetActiveWebContents(),
484       GURL("chrome-extension://thisissurelynotavalidextensionid/newtab.html"),
485       false, NULL));
486
487   // If we got to this point, we didn't crash, so we're good.
488 }
489
490 // Tests that calling window.open from the newtab page to an extension URL
491 // gives the new window extension privileges - even though the opening page
492 // does not have extension privileges, we break the script connection, so
493 // there is no privilege leak.
494 IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenNoPrivileges) {
495   ASSERT_TRUE(LoadExtension(
496       test_data_dir_.AppendASCII("uitest").AppendASCII("window_open")));
497
498   ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
499   WebContents* newtab = NULL;
500   ASSERT_NO_FATAL_FAILURE(
501       OpenWindow(browser()->tab_strip_model()->GetActiveWebContents(),
502                  GURL(std::string(extensions::kExtensionScheme) +
503                      url::kStandardSchemeSeparator +
504                      last_loaded_extension_id() + "/newtab.html"),
505                  false,
506                  &newtab));
507
508   // Extension API should succeed.
509   bool result = false;
510   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(newtab, "testExtensionApi()",
511                                                    &result));
512   EXPECT_TRUE(result);
513 }