Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / extension_action / browser_action_interactive_test.cc
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.
4
5 #include "chrome/browser/extensions/browser_action_test_util.h"
6 #include "chrome/browser/extensions/extension_action.h"
7 #include "chrome/browser/extensions/extension_action_manager.h"
8 #include "chrome/browser/extensions/extension_apitest.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_tab_util.h"
11 #include "chrome/browser/extensions/extension_test_message_listener.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_commands.h"
14 #include "chrome/browser/ui/browser_finder.h"
15 #include "chrome/browser/ui/browser_list.h"
16 #include "chrome/browser/ui/browser_window.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/test/base/interactive_test_utils.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/notification_service.h"
21 #include "extensions/browser/extension_registry.h"
22 #include "extensions/browser/extension_system.h"
23 #include "extensions/common/extension.h"
24 #include "extensions/common/extension_set.h"
25 #include "extensions/common/permissions/permissions_data.h"
26
27 #if defined(OS_WIN)
28 #include "ui/views/win/hwnd_util.h"
29 #endif
30
31 namespace extensions {
32 namespace {
33
34 // chrome.browserAction API tests that interact with the UI in such a way that
35 // they cannot be run concurrently (i.e. openPopup API tests that require the
36 // window be focused/active).
37 class BrowserActionInteractiveTest : public ExtensionApiTest {
38  public:
39   BrowserActionInteractiveTest() {}
40   virtual ~BrowserActionInteractiveTest() {}
41
42  protected:
43   // Function to control whether to run popup tests for the current platform.
44   // These tests require RunExtensionSubtest to work as expected and the browser
45   // window to able to be made active automatically. Returns false for platforms
46   // where these conditions are not met.
47   bool ShouldRunPopupTest() {
48     // TODO(justinlin): http://crbug.com/177163
49 #if defined(OS_WIN) && !defined(NDEBUG)
50     return false;
51 #elif defined(OS_MACOSX)
52     // TODO(justinlin): Browser window do not become active on Mac even when
53     // Activate() is called on them. Enable when/if it's possible to fix.
54     return false;
55 #else
56     return true;
57 #endif
58   }
59
60   // Open an extension popup via the chrome.browserAction.openPopup API.
61   void OpenExtensionPopupViaAPI() {
62     // Setup the notification observer to wait for the popup to finish loading.
63     content::WindowedNotificationObserver frame_observer(
64         content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
65         content::NotificationService::AllSources());
66     // Show first popup in first window and expect it to have loaded.
67     ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
68                                     "open_popup_succeeds.html")) << message_;
69     frame_observer.Wait();
70     EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
71   }
72 };
73
74 // Tests opening a popup using the chrome.browserAction.openPopup API. This test
75 // opens a popup in the starting window, closes the popup, creates a new window
76 // and opens a popup in the new window. Both popups should succeed in opening.
77 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TestOpenPopup) {
78   if (!ShouldRunPopupTest())
79     return;
80
81   BrowserActionTestUtil browserActionBar = BrowserActionTestUtil(browser());
82   // Setup extension message listener to wait for javascript to finish running.
83   ExtensionTestMessageListener listener("ready", true);
84   {
85     OpenExtensionPopupViaAPI();
86     EXPECT_TRUE(browserActionBar.HasPopup());
87     browserActionBar.HidePopup();
88   }
89
90   EXPECT_TRUE(listener.WaitUntilSatisfied());
91   Browser* new_browser = NULL;
92   {
93     content::WindowedNotificationObserver frame_observer(
94         content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
95         content::NotificationService::AllSources());
96     // Open a new window.
97     new_browser = chrome::FindBrowserWithWebContents(
98         browser()->OpenURL(content::OpenURLParams(
99             GURL("about:"), content::Referrer(), NEW_WINDOW,
100             content::PAGE_TRANSITION_TYPED, false)));
101 #if defined(OS_WIN)
102     // Hide all the buttons to test that it opens even when browser action is
103     // in the overflow bucket.
104     // TODO(justinlin): Implement for other platforms.
105     browserActionBar.SetIconVisibilityCount(0);
106 #endif
107     frame_observer.Wait();
108   }
109
110   EXPECT_TRUE(new_browser != NULL);
111
112 // Flaky on non-aura linux http://crbug.com/309749
113 #if !(defined(OS_LINUX) && !defined(USE_AURA))
114   ResultCatcher catcher;
115   {
116     content::WindowedNotificationObserver frame_observer(
117         content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
118         content::NotificationService::AllSources());
119     // Show second popup in new window.
120     listener.Reply("");
121     frame_observer.Wait();
122     EXPECT_TRUE(BrowserActionTestUtil(new_browser).HasPopup());
123   }
124   ASSERT_TRUE(catcher.GetNextResult()) << message_;
125 #endif
126 }
127
128 // Tests opening a popup in an incognito window.
129 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TestOpenPopupIncognito) {
130   if (!ShouldRunPopupTest())
131     return;
132
133   content::WindowedNotificationObserver frame_observer(
134       content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
135       content::NotificationService::AllSources());
136   ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
137                                   "open_popup_succeeds.html",
138                                   kFlagEnableIncognito | kFlagUseIncognito))
139       << message_;
140   frame_observer.Wait();
141   // Non-Aura Linux uses a singleton for the popup, so it looks like all windows
142   // have popups if there is any popup open.
143 #if !(defined(OS_LINUX) && !defined(USE_AURA))
144   // Starting window does not have a popup.
145   EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
146 #endif
147   // Incognito window should have a popup.
148   EXPECT_TRUE(BrowserActionTestUtil(BrowserList::GetInstance(
149       chrome::GetActiveDesktop())->GetLastActive()).HasPopup());
150 }
151
152 #if defined(OS_LINUX)
153 #define MAYBE_TestOpenPopupDoesNotCloseOtherPopups DISABLED_TestOpenPopupDoesNotCloseOtherPopups
154 #else
155 #define MAYBE_TestOpenPopupDoesNotCloseOtherPopups TestOpenPopupDoesNotCloseOtherPopups
156 #endif
157 // Tests if there is already a popup open (by a user click or otherwise), that
158 // the openPopup API does not override it.
159 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
160                        MAYBE_TestOpenPopupDoesNotCloseOtherPopups) {
161   if (!ShouldRunPopupTest())
162     return;
163
164   // Load a first extension that can open a popup.
165   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
166       "browser_action/popup")));
167   const Extension* extension = GetSingleLoadedExtension();
168   ASSERT_TRUE(extension) << message_;
169
170   ExtensionTestMessageListener listener("ready", true);
171   // Load the test extension which will do nothing except notifyPass() to
172   // return control here.
173   ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
174                                   "open_popup_fails.html")) << message_;
175   EXPECT_TRUE(listener.WaitUntilSatisfied());
176
177   content::WindowedNotificationObserver frame_observer(
178       content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
179       content::NotificationService::AllSources());
180   // Open popup in the first extension.
181   BrowserActionTestUtil(browser()).Press(0);
182   frame_observer.Wait();
183   EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
184
185   ResultCatcher catcher;
186   // Return control to javascript to validate that opening a popup fails now.
187   listener.Reply("");
188   ASSERT_TRUE(catcher.GetNextResult()) << message_;
189 }
190
191 // Test that openPopup does not grant tab permissions like for browser action
192 // clicks if the activeTab permission is set.
193 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
194                        TestOpenPopupDoesNotGrantTabPermissions) {
195   if (!ShouldRunPopupTest())
196     return;
197
198   OpenExtensionPopupViaAPI();
199   ExtensionService* service = extensions::ExtensionSystem::Get(
200       browser()->profile())->extension_service();
201   ASSERT_FALSE(
202       service->GetExtensionById(last_loaded_extension_id(), false)
203           ->permissions_data()
204           ->HasAPIPermissionForTab(
205               SessionID::IdForTab(
206                   browser()->tab_strip_model()->GetActiveWebContents()),
207               APIPermission::kTab));
208 }
209
210 // Test that the extension popup is closed when the browser window is clicked.
211 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, BrowserClickClosesPopup1) {
212   if (!ShouldRunPopupTest())
213     return;
214
215   // Open an extension popup via the chrome.browserAction.openPopup API.
216   content::WindowedNotificationObserver frame_observer(
217       content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
218       content::NotificationService::AllSources());
219   ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
220                                   "open_popup_succeeds.html")) << message_;
221   frame_observer.Wait();
222   EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
223
224   // Click on the omnibox to close the extension popup.
225   ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX);
226   EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
227 }
228
229 // Test that the extension popup is closed when the browser window is clicked.
230 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, BrowserClickClosesPopup2) {
231   if (!ShouldRunPopupTest())
232     return;
233
234   // Load a first extension that can open a popup.
235   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
236       "browser_action/popup")));
237   const Extension* extension = GetSingleLoadedExtension();
238   ASSERT_TRUE(extension) << message_;
239
240   // Open an extension popup by clicking the browser action button.
241   content::WindowedNotificationObserver frame_observer(
242       content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
243       content::NotificationService::AllSources());
244   BrowserActionTestUtil(browser()).Press(0);
245   frame_observer.Wait();
246   EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
247
248   // Click on the omnibox to close the extension popup.
249   ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX);
250   EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
251 }
252
253 // Test that the extension popup is closed on browser tab switches.
254 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TabSwitchClosesPopup) {
255   if (!ShouldRunPopupTest())
256     return;
257
258   // Add a second tab to the browser and open an extension popup.
259   chrome::NewTab(browser());
260   ASSERT_EQ(2, browser()->tab_strip_model()->count());
261   OpenExtensionPopupViaAPI();
262
263   // Press CTRL+TAB to change active tabs, the extension popup should close.
264   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
265       browser(), ui::VKEY_TAB, true, false, false, false));
266   EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
267 }
268
269 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
270                        DeleteBrowserActionWithPopupOpen) {
271   if (!ShouldRunPopupTest())
272     return;
273
274   // First, we open a popup.
275   OpenExtensionPopupViaAPI();
276   BrowserActionTestUtil browser_action_test_util(browser());
277   EXPECT_TRUE(browser_action_test_util.HasPopup());
278
279   // Then, find the extension that created it.
280   content::WebContents* active_web_contents =
281       browser()->tab_strip_model()->GetActiveWebContents();
282   ASSERT_TRUE(active_web_contents);
283   GURL url = active_web_contents->GetLastCommittedURL();
284   const Extension* extension = ExtensionRegistry::Get(browser()->profile())->
285       enabled_extensions().GetExtensionOrAppByURL(url);
286   ASSERT_TRUE(extension);
287
288   // Finally, uninstall the extension, which causes the view to be deleted and
289   // the popup to go away. This should not crash.
290   UninstallExtension(extension->id());
291   EXPECT_FALSE(browser_action_test_util.HasPopup());
292 }
293
294 #if defined(TOOLKIT_VIEWS)
295 // Test closing the browser while inspecting an extension popup with dev tools.
296 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, CloseBrowserWithDevTools) {
297   if (!ShouldRunPopupTest())
298     return;
299
300   // Load a first extension that can open a popup.
301   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
302       "browser_action/popup")));
303   const Extension* extension = GetSingleLoadedExtension();
304   ASSERT_TRUE(extension) << message_;
305
306   // Open an extension popup by clicking the browser action button.
307   content::WindowedNotificationObserver frame_observer(
308       content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
309       content::NotificationService::AllSources());
310   BrowserActionTestUtil(browser()).InspectPopup(0);
311   frame_observer.Wait();
312   EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
313
314   // Close the browser window, this should not cause a crash.
315   chrome::CloseWindow(browser());
316 }
317 #endif  // TOOLKIT_VIEWS
318
319 #if defined(OS_WIN)
320 // Test that forcibly closing the browser and popup HWND does not cause a crash.
321 // http://crbug.com/400646
322 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
323                        DISABLED_DestroyHWNDDoesNotCrash) {
324   if (!ShouldRunPopupTest())
325     return;
326
327   OpenExtensionPopupViaAPI();
328   BrowserActionTestUtil test_util(browser());
329   const gfx::NativeView view = test_util.GetPopupNativeView();
330   EXPECT_NE(static_cast<gfx::NativeView>(NULL), view);
331   const HWND hwnd = views::HWNDForNativeView(view);
332   EXPECT_EQ(hwnd,
333             views::HWNDForNativeView(browser()->window()->GetNativeWindow()));
334   EXPECT_EQ(TRUE, ::IsWindow(hwnd));
335
336   // Create a new browser window to prevent the message loop from terminating.
337   Browser* new_browser = chrome::FindBrowserWithWebContents(
338       browser()->OpenURL(content::OpenURLParams(
339           GURL("about:"), content::Referrer(), NEW_WINDOW,
340           content::PAGE_TRANSITION_TYPED, false)));
341
342   // Forcibly closing the browser HWND should not cause a crash.
343   EXPECT_EQ(TRUE, ::CloseWindow(hwnd));
344   EXPECT_EQ(TRUE, ::DestroyWindow(hwnd));
345   EXPECT_EQ(FALSE, ::IsWindow(hwnd));
346 }
347 #endif  // OS_WIN
348
349 }  // namespace
350 }  // namespace extensions