OLD | NEW |
| (Empty) |
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 "apps/launcher.h" | |
6 #include "apps/native_app_window.h" | |
7 #include "apps/shell_window.h" | |
8 #include "apps/shell_window_registry.h" | |
9 #include "base/bind.h" | |
10 #include "base/command_line.h" | |
11 #include "base/file_util.h" | |
12 #include "base/files/scoped_temp_dir.h" | |
13 #include "base/prefs/pref_service.h" | |
14 #include "base/stl_util.h" | |
15 #include "base/strings/utf_string_conversions.h" | |
16 #include "base/test/test_timeouts.h" | |
17 #include "base/threading/platform_thread.h" | |
18 #include "chrome/app/chrome_command_ids.h" | |
19 #include "chrome/browser/automation/automation_util.h" | |
20 #include "chrome/browser/chrome_notification_types.h" | |
21 #include "chrome/browser/devtools/devtools_window.h" | |
22 #include "chrome/browser/extensions/api/permissions/permissions_api.h" | |
23 #include "chrome/browser/extensions/component_loader.h" | |
24 #include "chrome/browser/extensions/event_names.h" | |
25 #include "chrome/browser/extensions/event_router.h" | |
26 #include "chrome/browser/extensions/extension_browsertest.h" | |
27 #include "chrome/browser/extensions/extension_prefs.h" | |
28 #include "chrome/browser/extensions/extension_service.h" | |
29 #include "chrome/browser/extensions/extension_system.h" | |
30 #include "chrome/browser/extensions/extension_test_message_listener.h" | |
31 #include "chrome/browser/extensions/platform_app_browsertest_util.h" | |
32 #include "chrome/browser/tab_contents/render_view_context_menu.h" | |
33 #include "chrome/browser/ui/browser.h" | |
34 #include "chrome/browser/ui/extensions/application_launch.h" | |
35 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
36 #include "chrome/common/chrome_switches.h" | |
37 #include "chrome/common/url_constants.h" | |
38 #include "chrome/test/base/test_switches.h" | |
39 #include "chrome/test/base/ui_test_utils.h" | |
40 #include "components/user_prefs/pref_registry_syncable.h" | |
41 #include "components/web_modal/web_contents_modal_dialog_manager.h" | |
42 #include "content/public/browser/devtools_agent_host.h" | |
43 #include "content/public/browser/render_process_host.h" | |
44 #include "content/public/browser/render_widget_host_view.h" | |
45 #include "content/public/browser/web_contents_view.h" | |
46 #include "content/public/test/test_utils.h" | |
47 #include "net/test/embedded_test_server/embedded_test_server.h" | |
48 #include "url/gurl.h" | |
49 | |
50 using apps::ShellWindow; | |
51 using apps::ShellWindowRegistry; | |
52 using content::WebContents; | |
53 using web_modal::WebContentsModalDialogManager; | |
54 | |
55 namespace extensions { | |
56 | |
57 namespace { | |
58 | |
59 // Non-abstract RenderViewContextMenu class. | |
60 class PlatformAppContextMenu : public RenderViewContextMenu { | |
61 public: | |
62 PlatformAppContextMenu(WebContents* web_contents, | |
63 const content::ContextMenuParams& params) | |
64 : RenderViewContextMenu(web_contents, params) {} | |
65 | |
66 bool HasCommandWithId(int command_id) { | |
67 return menu_model_.GetIndexOfCommandId(command_id) != -1; | |
68 } | |
69 | |
70 protected: | |
71 // RenderViewContextMenu implementation. | |
72 virtual bool GetAcceleratorForCommandId( | |
73 int command_id, | |
74 ui::Accelerator* accelerator) OVERRIDE { | |
75 return false; | |
76 } | |
77 virtual void PlatformInit() OVERRIDE {} | |
78 virtual void PlatformCancel() OVERRIDE {} | |
79 }; | |
80 | |
81 // This class keeps track of tabs as they are added to the browser. It will be | |
82 // "done" (i.e. won't block on Wait()) once |observations| tabs have been added. | |
83 class TabsAddedNotificationObserver | |
84 : public content::WindowedNotificationObserver { | |
85 public: | |
86 explicit TabsAddedNotificationObserver(size_t observations) | |
87 : content::WindowedNotificationObserver( | |
88 chrome::NOTIFICATION_TAB_ADDED, | |
89 content::NotificationService::AllSources()), | |
90 observations_(observations) { | |
91 } | |
92 | |
93 virtual void Observe(int type, | |
94 const content::NotificationSource& source, | |
95 const content::NotificationDetails& details) OVERRIDE { | |
96 observed_tabs_.push_back( | |
97 content::Details<WebContents>(details).ptr()); | |
98 if (observed_tabs_.size() == observations_) | |
99 content::WindowedNotificationObserver::Observe(type, source, details); | |
100 } | |
101 | |
102 const std::vector<content::WebContents*>& tabs() { return observed_tabs_; } | |
103 | |
104 private: | |
105 size_t observations_; | |
106 std::vector<content::WebContents*> observed_tabs_; | |
107 | |
108 DISALLOW_COPY_AND_ASSIGN(TabsAddedNotificationObserver); | |
109 }; | |
110 | |
111 bool CopyTestDataAndSetCommandLineArg( | |
112 const base::FilePath& test_data_file, | |
113 const base::FilePath& temp_dir, | |
114 const char* filename) { | |
115 base::FilePath path = temp_dir.AppendASCII( | |
116 filename).NormalizePathSeparators(); | |
117 if (!(base::CopyFile(test_data_file, path))) | |
118 return false; | |
119 | |
120 CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
121 command_line->AppendArgPath(path); | |
122 return true; | |
123 } | |
124 | |
125 const char kTestFilePath[] = "platform_apps/launch_files/test.txt"; | |
126 | |
127 } // namespace | |
128 | |
129 // Tests that CreateShellWindow doesn't crash if you close it straight away. | |
130 // LauncherPlatformAppBrowserTest relies on this behaviour, but is only run for | |
131 // ash, so we test that it works here. | |
132 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, CreateAndCloseShellWindow) { | |
133 const Extension* extension = LoadAndLaunchPlatformApp("minimal"); | |
134 ShellWindow* window = CreateShellWindow(extension); | |
135 CloseShellWindow(window); | |
136 } | |
137 | |
138 // Tests that platform apps received the "launch" event when launched. | |
139 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OnLaunchedEvent) { | |
140 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch")) << message_; | |
141 } | |
142 | |
143 // Tests that platform apps cannot use certain disabled window properties, but | |
144 // can override them and then use them. | |
145 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisabledWindowProperties) { | |
146 ASSERT_TRUE(RunPlatformAppTest("platform_apps/disabled_window_properties")) | |
147 << message_; | |
148 } | |
149 | |
150 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, EmptyContextMenu) { | |
151 ExtensionTestMessageListener launched_listener("Launched", false); | |
152 LoadAndLaunchPlatformApp("minimal"); | |
153 | |
154 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
155 | |
156 // The empty app doesn't add any context menu items, so its menu should | |
157 // only include the developer tools. | |
158 WebContents* web_contents = GetFirstShellWindowWebContents(); | |
159 ASSERT_TRUE(web_contents); | |
160 content::ContextMenuParams params; | |
161 scoped_ptr<PlatformAppContextMenu> menu; | |
162 menu.reset(new PlatformAppContextMenu(web_contents, params)); | |
163 menu->Init(); | |
164 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT)); | |
165 ASSERT_TRUE( | |
166 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE)); | |
167 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP)); | |
168 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK)); | |
169 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE)); | |
170 } | |
171 | |
172 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenu) { | |
173 ExtensionTestMessageListener launched_listener("Launched", false); | |
174 LoadAndLaunchPlatformApp("context_menu"); | |
175 | |
176 // Wait for the extension to tell us it's initialized its context menus and | |
177 // launched a window. | |
178 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
179 | |
180 // The context_menu app has two context menu items. These, along with a | |
181 // separator and the developer tools, is all that should be in the menu. | |
182 WebContents* web_contents = GetFirstShellWindowWebContents(); | |
183 ASSERT_TRUE(web_contents); | |
184 content::ContextMenuParams params; | |
185 scoped_ptr<PlatformAppContextMenu> menu; | |
186 menu.reset(new PlatformAppContextMenu(web_contents, params)); | |
187 menu->Init(); | |
188 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST)); | |
189 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1)); | |
190 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT)); | |
191 ASSERT_TRUE( | |
192 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE)); | |
193 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP)); | |
194 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK)); | |
195 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE)); | |
196 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO)); | |
197 } | |
198 | |
199 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, InstalledAppWithContextMenu) { | |
200 ExtensionTestMessageListener launched_listener("Launched", false); | |
201 InstallAndLaunchPlatformApp("context_menu"); | |
202 | |
203 // Wait for the extension to tell us it's initialized its context menus and | |
204 // launched a window. | |
205 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
206 | |
207 // The context_menu app has two context menu items. For an installed app | |
208 // these are all that should be in the menu. | |
209 WebContents* web_contents = GetFirstShellWindowWebContents(); | |
210 ASSERT_TRUE(web_contents); | |
211 content::ContextMenuParams params; | |
212 scoped_ptr<PlatformAppContextMenu> menu; | |
213 menu.reset(new PlatformAppContextMenu(web_contents, params)); | |
214 menu->Init(); | |
215 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST)); | |
216 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1)); | |
217 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT)); | |
218 ASSERT_FALSE( | |
219 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE)); | |
220 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP)); | |
221 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK)); | |
222 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE)); | |
223 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO)); | |
224 } | |
225 | |
226 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuTextField) { | |
227 ExtensionTestMessageListener launched_listener("Launched", false); | |
228 LoadAndLaunchPlatformApp("context_menu"); | |
229 | |
230 // Wait for the extension to tell us it's initialized its context menus and | |
231 // launched a window. | |
232 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
233 | |
234 // The context_menu app has one context menu item. This, along with a | |
235 // separator and the developer tools, is all that should be in the menu. | |
236 WebContents* web_contents = GetFirstShellWindowWebContents(); | |
237 ASSERT_TRUE(web_contents); | |
238 content::ContextMenuParams params; | |
239 params.is_editable = true; | |
240 scoped_ptr<PlatformAppContextMenu> menu; | |
241 menu.reset(new PlatformAppContextMenu(web_contents, params)); | |
242 menu->Init(); | |
243 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST)); | |
244 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT)); | |
245 ASSERT_TRUE( | |
246 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE)); | |
247 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP)); | |
248 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO)); | |
249 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY)); | |
250 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK)); | |
251 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE)); | |
252 } | |
253 | |
254 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuSelection) { | |
255 ExtensionTestMessageListener launched_listener("Launched", false); | |
256 LoadAndLaunchPlatformApp("context_menu"); | |
257 | |
258 // Wait for the extension to tell us it's initialized its context menus and | |
259 // launched a window. | |
260 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
261 | |
262 // The context_menu app has one context menu item. This, along with a | |
263 // separator and the developer tools, is all that should be in the menu. | |
264 WebContents* web_contents = GetFirstShellWindowWebContents(); | |
265 ASSERT_TRUE(web_contents); | |
266 content::ContextMenuParams params; | |
267 params.selection_text = ASCIIToUTF16("Hello World"); | |
268 scoped_ptr<PlatformAppContextMenu> menu; | |
269 menu.reset(new PlatformAppContextMenu(web_contents, params)); | |
270 menu->Init(); | |
271 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST)); | |
272 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT)); | |
273 ASSERT_TRUE( | |
274 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE)); | |
275 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP)); | |
276 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO)); | |
277 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY)); | |
278 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK)); | |
279 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE)); | |
280 } | |
281 | |
282 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuClicked) { | |
283 ExtensionTestMessageListener launched_listener("Launched", false); | |
284 LoadAndLaunchPlatformApp("context_menu_click"); | |
285 | |
286 // Wait for the extension to tell us it's initialized its context menus and | |
287 // launched a window. | |
288 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
289 | |
290 // Test that the menu item shows up | |
291 WebContents* web_contents = GetFirstShellWindowWebContents(); | |
292 ASSERT_TRUE(web_contents); | |
293 content::ContextMenuParams params; | |
294 params.page_url = GURL("http://foo.bar"); | |
295 scoped_ptr<PlatformAppContextMenu> menu; | |
296 menu.reset(new PlatformAppContextMenu(web_contents, params)); | |
297 menu->Init(); | |
298 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST)); | |
299 | |
300 // Execute the menu item | |
301 ExtensionTestMessageListener onclicked_listener("onClicked fired for id1", | |
302 false); | |
303 menu->ExecuteCommand(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST, 0); | |
304 | |
305 ASSERT_TRUE(onclicked_listener.WaitUntilSatisfied()); | |
306 } | |
307 | |
308 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowNavigation) { | |
309 TabsAddedNotificationObserver observer(2); | |
310 | |
311 ASSERT_TRUE(StartEmbeddedTestServer()); | |
312 ASSERT_TRUE(RunPlatformAppTest("platform_apps/navigation")) << message_; | |
313 | |
314 observer.Wait(); | |
315 ASSERT_EQ(2U, observer.tabs().size()); | |
316 EXPECT_EQ(std::string(chrome::kExtensionInvalidRequestURL), | |
317 observer.tabs()[0]->GetURL().spec()); | |
318 EXPECT_EQ("http://chromium.org/", | |
319 observer.tabs()[1]->GetURL().spec()); | |
320 } | |
321 | |
322 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Iframes) { | |
323 ASSERT_TRUE(StartEmbeddedTestServer()); | |
324 ASSERT_TRUE(RunPlatformAppTest("platform_apps/iframes")) << message_; | |
325 } | |
326 | |
327 // Tests that localStorage and WebSQL are disabled for platform apps. | |
328 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowStorage) { | |
329 ASSERT_TRUE(RunPlatformAppTest("platform_apps/storage")) << message_; | |
330 } | |
331 | |
332 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Restrictions) { | |
333 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restrictions")) << message_; | |
334 } | |
335 | |
336 // Tests that platform apps can use the chrome.app.window.* API. | |
337 // It is flaky: http://crbug.com/223467 | |
338 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DISABLED_WindowsApi) { | |
339 ASSERT_TRUE(RunPlatformAppTest("platform_apps/windows_api")) << message_; | |
340 } | |
341 | |
342 // Tests that extensions can't use platform-app-only APIs. | |
343 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, PlatformAppsOnly) { | |
344 ASSERT_TRUE(RunExtensionTestIgnoreManifestWarnings( | |
345 "platform_apps/apps_only")) << message_; | |
346 } | |
347 | |
348 // Tests that platform apps have isolated storage by default. | |
349 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Isolation) { | |
350 ASSERT_TRUE(StartEmbeddedTestServer()); | |
351 | |
352 // Load a (non-app) page under the "localhost" origin that sets a cookie. | |
353 GURL set_cookie_url = embedded_test_server()->GetURL( | |
354 "/extensions/platform_apps/isolation/set_cookie.html"); | |
355 GURL::Replacements replace_host; | |
356 std::string host_str("localhost"); // Must stay in scope with replace_host. | |
357 replace_host.SetHostStr(host_str); | |
358 set_cookie_url = set_cookie_url.ReplaceComponents(replace_host); | |
359 | |
360 ui_test_utils::NavigateToURLWithDisposition( | |
361 browser(), set_cookie_url, | |
362 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); | |
363 | |
364 // Make sure the cookie is set. | |
365 int cookie_size; | |
366 std::string cookie_value; | |
367 automation_util::GetCookies( | |
368 set_cookie_url, | |
369 browser()->tab_strip_model()->GetWebContentsAt(0), | |
370 &cookie_size, | |
371 &cookie_value); | |
372 ASSERT_EQ("testCookie=1", cookie_value); | |
373 | |
374 // Let the platform app request the same URL, and make sure that it doesn't | |
375 // see the cookie. | |
376 ASSERT_TRUE(RunPlatformAppTest("platform_apps/isolation")) << message_; | |
377 } | |
378 | |
379 // See crbug.com/248441 | |
380 #if defined(OS_WIN) | |
381 #define MAYBE_ExtensionWindowingApis DISABLED_ExtensionWindowingApis | |
382 #else | |
383 #define MAYBE_ExtensionWindowingApis ExtensionWindowingApis | |
384 #endif | |
385 | |
386 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ExtensionWindowingApis) { | |
387 // Initially there should be just the one browser window visible to the | |
388 // extensions API. | |
389 const Extension* extension = LoadExtension( | |
390 test_data_dir_.AppendASCII("common/background_page")); | |
391 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension)); | |
392 | |
393 // And no shell windows. | |
394 ASSERT_EQ(0U, GetShellWindowCount()); | |
395 | |
396 // Launch a platform app that shows a window. | |
397 ExtensionTestMessageListener launched_listener("Launched", false); | |
398 LoadAndLaunchPlatformApp("minimal"); | |
399 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
400 ASSERT_EQ(1U, GetShellWindowCount()); | |
401 ShellWindowRegistry::ShellWindowList shell_windows = | |
402 ShellWindowRegistry::Get(browser()->profile())->shell_windows(); | |
403 int shell_window_id = (*shell_windows.begin())->session_id().id(); | |
404 | |
405 // But it's not visible to the extensions API, it still thinks there's just | |
406 // one browser window. | |
407 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension)); | |
408 // It can't look it up by ID either | |
409 ASSERT_FALSE(RunGetWindowFunctionForExtension(shell_window_id, extension)); | |
410 | |
411 // The app can also only see one window (its own). | |
412 // TODO(jeremya): add an extension function to get a shell window by ID, and | |
413 // to get a list of all the shell windows, so we can test this. | |
414 | |
415 // Launch another platform app that also shows a window. | |
416 ExtensionTestMessageListener launched_listener2("Launched", false); | |
417 LoadAndLaunchPlatformApp("context_menu"); | |
418 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied()); | |
419 | |
420 // There are two total shell windows, but each app can only see its own. | |
421 ASSERT_EQ(2U, GetShellWindowCount()); | |
422 // TODO(jeremya): as above, this requires more extension functions. | |
423 } | |
424 | |
425 // ChromeOS does not support passing arguments on the command line, so the tests | |
426 // that rely on this functionality are disabled. | |
427 #if !defined(OS_CHROMEOS) | |
428 // Tests that command line parameters get passed through to platform apps | |
429 // via launchData correctly when launching with a file. | |
430 // TODO(benwells/jeremya): tests need a way to specify a handler ID. | |
431 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFile) { | |
432 SetCommandLineArg(kTestFilePath); | |
433 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file")) | |
434 << message_; | |
435 } | |
436 | |
437 // Tests that relative paths can be passed through to the platform app. | |
438 // This test doesn't use the normal test infrastructure as it needs to open | |
439 // the application differently to all other platform app tests, by setting | |
440 // the chrome::AppLaunchParams.current_directory field. | |
441 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithRelativeFile) { | |
442 // Setup the command line | |
443 ClearCommandLineArgs(); | |
444 CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
445 base::FilePath relative_test_doc = | |
446 base::FilePath::FromUTF8Unsafe(kTestFilePath); | |
447 relative_test_doc = relative_test_doc.NormalizePathSeparators(); | |
448 command_line->AppendArgPath(relative_test_doc); | |
449 | |
450 // Load the extension | |
451 ResultCatcher catcher; | |
452 const Extension* extension = LoadExtension( | |
453 test_data_dir_.AppendASCII("platform_apps/launch_file")); | |
454 ASSERT_TRUE(extension); | |
455 | |
456 // Run the test | |
457 chrome::AppLaunchParams params(browser()->profile(), extension, | |
458 extension_misc::LAUNCH_NONE, NEW_WINDOW); | |
459 params.command_line = CommandLine::ForCurrentProcess(); | |
460 params.current_directory = test_data_dir_; | |
461 chrome::OpenApplication(params); | |
462 | |
463 if (!catcher.GetNextResult()) { | |
464 message_ = catcher.message(); | |
465 ASSERT_TRUE(0); | |
466 } | |
467 } | |
468 | |
469 // Tests that launch data is sent through if the file extension matches. | |
470 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFileExtension) { | |
471 SetCommandLineArg(kTestFilePath); | |
472 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file_by_extension")) | |
473 << message_; | |
474 } | |
475 | |
476 // Tests that launch data is sent through if the file extension and MIME type | |
477 // both match. | |
478 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, | |
479 LaunchWithFileExtensionAndMimeType) { | |
480 SetCommandLineArg(kTestFilePath); | |
481 ASSERT_TRUE(RunPlatformAppTest( | |
482 "platform_apps/launch_file_by_extension_and_type")) << message_; | |
483 } | |
484 | |
485 // Tests that launch data is sent through for a file with no extension if a | |
486 // handler accepts "". | |
487 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFileWithoutExtension) { | |
488 SetCommandLineArg("platform_apps/launch_files/test"); | |
489 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file_with_no_extension")) | |
490 << message_; | |
491 } | |
492 | |
493 #if !defined(OS_WIN) | |
494 // Tests that launch data is sent through for a file with an empty extension if | |
495 // a handler accepts "". | |
496 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFileEmptyExtension) { | |
497 base::ScopedTempDir temp_dir; | |
498 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
499 ClearCommandLineArgs(); | |
500 ASSERT_TRUE(CopyTestDataAndSetCommandLineArg( | |
501 test_data_dir_.AppendASCII(kTestFilePath), | |
502 temp_dir.path(), | |
503 "test.")); | |
504 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file_with_no_extension")) | |
505 << message_; | |
506 } | |
507 | |
508 // Tests that launch data is sent through for a file with an empty extension if | |
509 // a handler accepts *. | |
510 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, | |
511 LaunchWithFileEmptyExtensionAcceptAny) { | |
512 base::ScopedTempDir temp_dir; | |
513 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
514 ClearCommandLineArgs(); | |
515 ASSERT_TRUE(CopyTestDataAndSetCommandLineArg( | |
516 test_data_dir_.AppendASCII(kTestFilePath), | |
517 temp_dir.path(), | |
518 "test.")); | |
519 ASSERT_TRUE(RunPlatformAppTest( | |
520 "platform_apps/launch_file_with_any_extension")) << message_; | |
521 } | |
522 #endif | |
523 | |
524 // Tests that launch data is sent through for a file with no extension if a | |
525 // handler accepts *. | |
526 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, | |
527 LaunchWithFileWithoutExtensionAcceptAny) { | |
528 SetCommandLineArg("platform_apps/launch_files/test"); | |
529 ASSERT_TRUE(RunPlatformAppTest( | |
530 "platform_apps/launch_file_with_any_extension")) << message_; | |
531 } | |
532 | |
533 // Tests that launch data is sent through for a file with an extension if a | |
534 // handler accepts *. | |
535 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, | |
536 LaunchWithFileAcceptAnyExtension) { | |
537 SetCommandLineArg(kTestFilePath); | |
538 ASSERT_TRUE(RunPlatformAppTest( | |
539 "platform_apps/launch_file_with_any_extension")) << message_; | |
540 } | |
541 | |
542 // Tests that no launch data is sent through if the file has the wrong | |
543 // extension. | |
544 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongExtension) { | |
545 SetCommandLineArg(kTestFilePath); | |
546 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_extension")) | |
547 << message_; | |
548 } | |
549 | |
550 // Tests that no launch data is sent through if the file has no extension but | |
551 // the handler requires a specific extension. | |
552 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongEmptyExtension) { | |
553 SetCommandLineArg("platform_apps/launch_files/test"); | |
554 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_extension")) | |
555 << message_; | |
556 } | |
557 | |
558 // Tests that no launch data is sent through if the file is of the wrong MIME | |
559 // type. | |
560 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongType) { | |
561 SetCommandLineArg(kTestFilePath); | |
562 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_type")) | |
563 << message_; | |
564 } | |
565 | |
566 // Tests that no launch data is sent through if the platform app does not | |
567 // provide an intent. | |
568 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNoIntent) { | |
569 SetCommandLineArg(kTestFilePath); | |
570 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_no_intent")) | |
571 << message_; | |
572 } | |
573 | |
574 // Tests that launch data is sent through with the MIME type set to | |
575 // application/octet-stream if the file MIME type cannot be read. | |
576 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoType) { | |
577 SetCommandLineArg("platform_apps/launch_files/test.unknownextension"); | |
578 ASSERT_TRUE(RunPlatformAppTest( | |
579 "platform_apps/launch_application_octet_stream")) << message_; | |
580 } | |
581 | |
582 // Tests that no launch data is sent through if the file does not exist. | |
583 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoFile) { | |
584 SetCommandLineArg("platform_apps/launch_files/doesnotexist.txt"); | |
585 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid")) | |
586 << message_; | |
587 } | |
588 | |
589 // Tests that no launch data is sent through if the argument is a directory. | |
590 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithDirectory) { | |
591 SetCommandLineArg("platform_apps/launch_files"); | |
592 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid")) | |
593 << message_; | |
594 } | |
595 | |
596 // Tests that no launch data is sent through if there are no arguments passed | |
597 // on the command line | |
598 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNothing) { | |
599 ClearCommandLineArgs(); | |
600 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_nothing")) | |
601 << message_; | |
602 } | |
603 | |
604 // Test that platform apps can use the chrome.fileSystem.getDisplayPath | |
605 // function to get the native file system path of a file they are launched with. | |
606 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, GetDisplayPath) { | |
607 SetCommandLineArg(kTestFilePath); | |
608 ASSERT_TRUE(RunPlatformAppTest("platform_apps/get_display_path")) | |
609 << message_; | |
610 } | |
611 | |
612 #endif // defined(OS_CHROMEOS) | |
613 | |
614 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OpenLink) { | |
615 ASSERT_TRUE(StartEmbeddedTestServer()); | |
616 content::WindowedNotificationObserver observer( | |
617 chrome::NOTIFICATION_TAB_ADDED, | |
618 content::Source<content::WebContentsDelegate>(browser())); | |
619 LoadAndLaunchPlatformApp("open_link"); | |
620 observer.Wait(); | |
621 ASSERT_EQ(2, browser()->tab_strip_model()->count()); | |
622 } | |
623 | |
624 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MutationEventsDisabled) { | |
625 ASSERT_TRUE(RunPlatformAppTest("platform_apps/mutation_events")) << message_; | |
626 } | |
627 | |
628 // Test that windows created with an id will remember and restore their | |
629 // geometry when opening new windows. | |
630 // Originally disabled due to flakiness (see http://crbug.com/155459) | |
631 // but now because a regression breaks the test (http://crbug.com/160343). | |
632 #if defined(TOOLKIT_GTK) | |
633 #define MAYBE_ShellWindowRestorePosition DISABLED_ShellWindowRestorePosition | |
634 #else | |
635 #define MAYBE_ShellWindowRestorePosition ShellWindowRestorePosition | |
636 #endif | |
637 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, | |
638 MAYBE_ShellWindowRestorePosition) { | |
639 ASSERT_TRUE(RunPlatformAppTest("platform_apps/geometry")); | |
640 } | |
641 | |
642 // This appears to be unreliable on linux. | |
643 // TODO(stevenjb): Investigate and enable | |
644 #if defined(OS_LINUX) && !defined(USE_ASH) | |
645 #define MAYBE_ShellWindowRestoreState DISABLED_ShellWindowRestoreState | |
646 #else | |
647 #define MAYBE_ShellWindowRestoreState ShellWindowRestoreState | |
648 #endif | |
649 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, | |
650 MAYBE_ShellWindowRestoreState) { | |
651 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restore_state")); | |
652 } | |
653 | |
654 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, | |
655 ShellWindowAdjustBoundsToBeVisibleOnScreen) { | |
656 const Extension* extension = LoadAndLaunchPlatformApp("minimal"); | |
657 ShellWindow* window = CreateShellWindow(extension); | |
658 | |
659 // The screen bounds didn't change, the cached bounds didn't need to adjust. | |
660 gfx::Rect cached_bounds(80, 100, 400, 400); | |
661 gfx::Rect cached_screen_bounds(0, 0, 1600, 900); | |
662 gfx::Rect current_screen_bounds(0, 0, 1600, 900); | |
663 gfx::Size minimum_size(200, 200); | |
664 gfx::Rect bounds; | |
665 CallAdjustBoundsToBeVisibleOnScreenForShellWindow(window, | |
666 cached_bounds, | |
667 cached_screen_bounds, | |
668 current_screen_bounds, | |
669 minimum_size, | |
670 &bounds); | |
671 EXPECT_EQ(bounds, cached_bounds); | |
672 | |
673 // We have an empty screen bounds, the cached bounds didn't need to adjust. | |
674 gfx::Rect empty_screen_bounds; | |
675 CallAdjustBoundsToBeVisibleOnScreenForShellWindow(window, | |
676 cached_bounds, | |
677 empty_screen_bounds, | |
678 current_screen_bounds, | |
679 minimum_size, | |
680 &bounds); | |
681 EXPECT_EQ(bounds, cached_bounds); | |
682 | |
683 // Cached bounds is completely off the new screen bounds in horizontal | |
684 // locations. Expect to reposition the bounds. | |
685 gfx::Rect horizontal_out_of_screen_bounds(-800, 100, 400, 400); | |
686 CallAdjustBoundsToBeVisibleOnScreenForShellWindow( | |
687 window, | |
688 horizontal_out_of_screen_bounds, | |
689 gfx::Rect(-1366, 0, 1600, 900), | |
690 current_screen_bounds, | |
691 minimum_size, | |
692 &bounds); | |
693 EXPECT_EQ(bounds, gfx::Rect(0, 100, 400, 400)); | |
694 | |
695 // Cached bounds is completely off the new screen bounds in vertical | |
696 // locations. Expect to reposition the bounds. | |
697 gfx::Rect vertical_out_of_screen_bounds(10, 1000, 400, 400); | |
698 CallAdjustBoundsToBeVisibleOnScreenForShellWindow( | |
699 window, | |
700 vertical_out_of_screen_bounds, | |
701 gfx::Rect(-1366, 0, 1600, 900), | |
702 current_screen_bounds, | |
703 minimum_size, | |
704 &bounds); | |
705 EXPECT_EQ(bounds, gfx::Rect(10, 500, 400, 400)); | |
706 | |
707 // From a large screen resulotion to a small one. Expect it fit on screen. | |
708 gfx::Rect big_cache_bounds(10, 10, 1000, 1000); | |
709 CallAdjustBoundsToBeVisibleOnScreenForShellWindow( | |
710 window, | |
711 big_cache_bounds, | |
712 gfx::Rect(0, 0, 1600, 1000), | |
713 gfx::Rect(0, 0, 800, 600), | |
714 minimum_size, | |
715 &bounds); | |
716 EXPECT_EQ(bounds, gfx::Rect(0, 0, 800, 600)); | |
717 | |
718 // Don't resize the bounds smaller than minimum size, when the minimum size is | |
719 // larger than the screen. | |
720 CallAdjustBoundsToBeVisibleOnScreenForShellWindow( | |
721 window, | |
722 big_cache_bounds, | |
723 gfx::Rect(0, 0, 1600, 1000), | |
724 gfx::Rect(0, 0, 800, 600), | |
725 gfx::Size(900, 900), | |
726 &bounds); | |
727 EXPECT_EQ(bounds, gfx::Rect(0, 0, 900, 900)); | |
728 } | |
729 | |
730 namespace { | |
731 | |
732 class PlatformAppDevToolsBrowserTest : public PlatformAppBrowserTest { | |
733 protected: | |
734 enum TestFlags { | |
735 RELAUNCH = 0x1, | |
736 HAS_ID = 0x2, | |
737 }; | |
738 // Runs a test inside a harness that opens DevTools on a shell window. | |
739 void RunTestWithDevTools(const char* name, int test_flags); | |
740 }; | |
741 | |
742 void PlatformAppDevToolsBrowserTest::RunTestWithDevTools( | |
743 const char* name, int test_flags) { | |
744 using content::DevToolsAgentHost; | |
745 ExtensionTestMessageListener launched_listener("Launched", false); | |
746 const Extension* extension = LoadAndLaunchPlatformApp(name); | |
747 ASSERT_TRUE(extension); | |
748 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
749 ShellWindow* window = GetFirstShellWindow(); | |
750 ASSERT_TRUE(window); | |
751 ASSERT_EQ(window->window_key().empty(), (test_flags & HAS_ID) == 0); | |
752 content::RenderViewHost* rvh = window->web_contents()->GetRenderViewHost(); | |
753 ASSERT_TRUE(rvh); | |
754 | |
755 // Ensure no DevTools open for the ShellWindow, then open one. | |
756 ASSERT_FALSE(DevToolsAgentHost::HasFor(rvh)); | |
757 DevToolsWindow* devtools_window = DevToolsWindow::OpenDevToolsWindow(rvh); | |
758 content::WindowedNotificationObserver loaded_observer( | |
759 content::NOTIFICATION_LOAD_STOP, | |
760 content::Source<content::NavigationController>( | |
761 &devtools_window->web_contents()->GetController())); | |
762 loaded_observer.Wait(); | |
763 ASSERT_TRUE(DevToolsAgentHost::HasFor(rvh)); | |
764 | |
765 if (test_flags & RELAUNCH) { | |
766 // Close the ShellWindow, and ensure it is gone. | |
767 CloseShellWindow(window); | |
768 ASSERT_FALSE(GetFirstShellWindow()); | |
769 | |
770 // Relaunch the app and get a new ShellWindow. | |
771 content::WindowedNotificationObserver app_loaded_observer( | |
772 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, | |
773 content::NotificationService::AllSources()); | |
774 chrome::OpenApplication(chrome::AppLaunchParams(browser()->profile(), | |
775 extension, | |
776 extension_misc::LAUNCH_NONE, | |
777 NEW_WINDOW)); | |
778 app_loaded_observer.Wait(); | |
779 window = GetFirstShellWindow(); | |
780 ASSERT_TRUE(window); | |
781 | |
782 // DevTools should have reopened with the relaunch. | |
783 rvh = window->web_contents()->GetRenderViewHost(); | |
784 ASSERT_TRUE(rvh); | |
785 ASSERT_TRUE(DevToolsAgentHost::HasFor(rvh)); | |
786 } | |
787 } | |
788 | |
789 } // namespace | |
790 | |
791 // http://crbug.com/246634 | |
792 #if defined(OS_CHROMEOS) | |
793 #define MAYBE_ReOpenedWithID DISABLED_ReOpenedWithID | |
794 #else | |
795 #define MAYBE_ReOpenedWithID ReOpenedWithID | |
796 #endif | |
797 IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, MAYBE_ReOpenedWithID) { | |
798 #if defined(OS_WIN) && defined(USE_ASH) | |
799 // Disable this test in Metro+Ash for now (http://crbug.com/262796). | |
800 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) | |
801 return; | |
802 #endif | |
803 RunTestWithDevTools("minimal_id", RELAUNCH | HAS_ID); | |
804 } | |
805 | |
806 // http://crbug.com/246999 | |
807 #if defined(OS_CHROMEOS) || defined(OS_WIN) | |
808 #define MAYBE_ReOpenedWithURL DISABLED_ReOpenedWithURL | |
809 #else | |
810 #define MAYBE_ReOpenedWithURL ReOpenedWithURL | |
811 #endif | |
812 IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, MAYBE_ReOpenedWithURL) { | |
813 RunTestWithDevTools("minimal", RELAUNCH); | |
814 } | |
815 | |
816 // Test that showing a permission request as a constrained window works and is | |
817 // correctly parented. | |
818 #if defined(OS_MACOSX) | |
819 #define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest | |
820 #else | |
821 // TODO(sail): Enable this on other platforms once http://crbug.com/95455 is | |
822 // fixed. | |
823 #define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest | |
824 #endif | |
825 | |
826 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ConstrainedWindowRequest) { | |
827 PermissionsRequestFunction::SetIgnoreUserGestureForTests(true); | |
828 const Extension* extension = | |
829 LoadAndLaunchPlatformApp("optional_permission_request"); | |
830 ASSERT_TRUE(extension) << "Failed to load extension."; | |
831 | |
832 WebContents* web_contents = GetFirstShellWindowWebContents(); | |
833 ASSERT_TRUE(web_contents); | |
834 | |
835 // Verify that the shell window has a dialog attached. | |
836 WebContentsModalDialogManager* web_contents_modal_dialog_manager = | |
837 WebContentsModalDialogManager::FromWebContents(web_contents); | |
838 EXPECT_TRUE(web_contents_modal_dialog_manager->IsShowingDialog()); | |
839 | |
840 // Close the constrained window and wait for the reply to the permission | |
841 // request. | |
842 ExtensionTestMessageListener listener("PermissionRequestDone", false); | |
843 WebContentsModalDialogManager::TestApi test_api( | |
844 web_contents_modal_dialog_manager); | |
845 test_api.CloseAllDialogs(); | |
846 ASSERT_TRUE(listener.WaitUntilSatisfied()); | |
847 } | |
848 | |
849 // Tests that an app calling chrome.runtime.reload will reload the app and | |
850 // relaunch it if it was running. | |
851 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReloadRelaunches) { | |
852 ExtensionTestMessageListener launched_listener("Launched", true); | |
853 const Extension* extension = LoadAndLaunchPlatformApp("reload"); | |
854 ASSERT_TRUE(extension); | |
855 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
856 ASSERT_TRUE(GetFirstShellWindow()); | |
857 | |
858 // Now tell the app to reload itself | |
859 ExtensionTestMessageListener launched_listener2("Launched", false); | |
860 launched_listener.Reply("reload"); | |
861 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied()); | |
862 ASSERT_TRUE(GetFirstShellWindow()); | |
863 } | |
864 | |
865 namespace { | |
866 | |
867 // Simple observer to check for NOTIFICATION_EXTENSION_INSTALLED events to | |
868 // ensure installation does or does not occur in certain scenarios. | |
869 class CheckExtensionInstalledObserver : public content::NotificationObserver { | |
870 public: | |
871 CheckExtensionInstalledObserver() : seen_(false) { | |
872 registrar_.Add(this, | |
873 chrome::NOTIFICATION_EXTENSION_INSTALLED, | |
874 content::NotificationService::AllSources()); | |
875 } | |
876 | |
877 bool seen() const { | |
878 return seen_; | |
879 }; | |
880 | |
881 // NotificationObserver: | |
882 virtual void Observe(int type, | |
883 const content::NotificationSource& source, | |
884 const content::NotificationDetails& details) OVERRIDE { | |
885 EXPECT_FALSE(seen_); | |
886 seen_ = true; | |
887 } | |
888 | |
889 private: | |
890 bool seen_; | |
891 content::NotificationRegistrar registrar_; | |
892 }; | |
893 | |
894 } // namespace | |
895 | |
896 // Component App Test 1 of 3: ensure that the initial load of a component | |
897 // extension utilizing a background page (e.g. a v2 platform app) has its | |
898 // background page run and is launchable. Waits for the Launched response from | |
899 // the script resource in the opened shell window. | |
900 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, | |
901 PRE_PRE_ComponentAppBackgroundPage) { | |
902 CheckExtensionInstalledObserver should_install; | |
903 | |
904 // Ensure that we wait until the background page is run (to register the | |
905 // OnLaunched listener) before trying to open the application. This is similar | |
906 // to LoadAndLaunchPlatformApp, but we want to load as a component extension. | |
907 content::WindowedNotificationObserver app_loaded_observer( | |
908 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, | |
909 content::NotificationService::AllSources()); | |
910 | |
911 const Extension* extension = LoadExtensionAsComponent( | |
912 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component")); | |
913 ASSERT_TRUE(extension); | |
914 | |
915 app_loaded_observer.Wait(); | |
916 ASSERT_TRUE(should_install.seen()); | |
917 | |
918 ExtensionTestMessageListener launched_listener("Launched", false); | |
919 chrome::OpenApplication(chrome::AppLaunchParams(browser()->profile(), | |
920 extension, | |
921 extension_misc::LAUNCH_NONE, | |
922 NEW_WINDOW)); | |
923 | |
924 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
925 } | |
926 | |
927 // Component App Test 2 of 3: ensure an installed component app can be launched | |
928 // on a subsequent browser start, without requiring any install/upgrade logic | |
929 // to be run, then perform setup for step 3. | |
930 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, | |
931 PRE_ComponentAppBackgroundPage) { | |
932 | |
933 // Since the component app is now installed, re-adding it in the same profile | |
934 // should not cause it to be re-installed. Instead, we wait for the OnLaunched | |
935 // in a different observer (which would timeout if not the app was not | |
936 // previously installed properly) and then check this observer to make sure it | |
937 // never saw the NOTIFICATION_EXTENSION_INSTALLED event. | |
938 CheckExtensionInstalledObserver should_not_install; | |
939 const Extension* extension = LoadExtensionAsComponent( | |
940 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component")); | |
941 ASSERT_TRUE(extension); | |
942 | |
943 ExtensionTestMessageListener launched_listener("Launched", false); | |
944 chrome::OpenApplication(chrome::AppLaunchParams(browser()->profile(), | |
945 extension, | |
946 extension_misc::LAUNCH_NONE, | |
947 NEW_WINDOW)); | |
948 | |
949 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
950 ASSERT_FALSE(should_not_install.seen()); | |
951 | |
952 // Simulate a "downgrade" from version 2 in the test manifest.json to 1. | |
953 ExtensionPrefs* extension_prefs = | |
954 extensions::ExtensionSystem::Get(browser()->profile())-> | |
955 extension_service()->extension_prefs(); | |
956 | |
957 // Clear the registered events to ensure they are updated. | |
958 extensions::ExtensionSystem::Get(browser()->profile())->event_router()-> | |
959 SetRegisteredEvents(extension->id(), std::set<std::string>()); | |
960 | |
961 DictionaryPrefUpdate update(extension_prefs->pref_service(), | |
962 ExtensionPrefs::kExtensionsPref); | |
963 DictionaryValue* dict = update.Get(); | |
964 std::string key(extension->id()); | |
965 key += ".manifest.version"; | |
966 dict->SetString(key, "1"); | |
967 } | |
968 | |
969 // Component App Test 3 of 3: simulate a component extension upgrade that | |
970 // re-adds the OnLaunched event, and allows the app to be launched. | |
971 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ComponentAppBackgroundPage) { | |
972 CheckExtensionInstalledObserver should_install; | |
973 // Since we are forcing an upgrade, we need to wait for the load again. | |
974 content::WindowedNotificationObserver app_loaded_observer( | |
975 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, | |
976 content::NotificationService::AllSources()); | |
977 | |
978 const Extension* extension = LoadExtensionAsComponent( | |
979 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component")); | |
980 ASSERT_TRUE(extension); | |
981 app_loaded_observer.Wait(); | |
982 ASSERT_TRUE(should_install.seen()); | |
983 | |
984 ExtensionTestMessageListener launched_listener("Launched", false); | |
985 chrome::OpenApplication(chrome::AppLaunchParams(browser()->profile(), | |
986 extension, | |
987 extension_misc::LAUNCH_NONE, | |
988 NEW_WINDOW)); | |
989 | |
990 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
991 } | |
992 | |
993 // Flakes on Windows: http://crbug.com/171450 | |
994 #if defined(OS_WIN) | |
995 #define MAYBE_Messaging DISABLED_Messaging | |
996 #else | |
997 #define MAYBE_Messaging Messaging | |
998 #endif | |
999 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_Messaging) { | |
1000 ExtensionApiTest::ResultCatcher result_catcher; | |
1001 LoadAndLaunchPlatformApp("messaging/app2"); | |
1002 LoadAndLaunchPlatformApp("messaging/app1"); | |
1003 EXPECT_TRUE(result_catcher.GetNextResult()); | |
1004 } | |
1005 | |
1006 // TODO(linux_aura) http://crbug.com/163931 | |
1007 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) | |
1008 #define MAYBE_WebContentsHasFocus DISABLED_WebContentsHasFocus | |
1009 #else | |
1010 // This test depends on focus and so needs to be in interactive_ui_tests. | |
1011 // http://crbug.com/227041 | |
1012 #define MAYBE_WebContentsHasFocus DISABLED_WebContentsHasFocus | |
1013 #endif | |
1014 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_WebContentsHasFocus) { | |
1015 ExtensionTestMessageListener launched_listener("Launched", true); | |
1016 LoadAndLaunchPlatformApp("minimal"); | |
1017 ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); | |
1018 | |
1019 EXPECT_EQ(1LU, GetShellWindowCount()); | |
1020 ShellWindowRegistry::ShellWindowList shell_windows = ShellWindowRegistry::Get( | |
1021 browser()->profile())->shell_windows(); | |
1022 EXPECT_TRUE((*shell_windows.begin())->web_contents()-> | |
1023 GetRenderWidgetHostView()->HasFocus()); | |
1024 } | |
1025 | |
1026 | |
1027 #if defined(OS_CHROMEOS) | |
1028 | |
1029 class PlatformAppIncognitoBrowserTest : public PlatformAppBrowserTest, | |
1030 public ShellWindowRegistry::Observer { | |
1031 public: | |
1032 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
1033 // Tell chromeos to launch in Guest mode, aka incognito. | |
1034 command_line->AppendSwitch(switches::kIncognito); | |
1035 PlatformAppBrowserTest::SetUpCommandLine(command_line); | |
1036 } | |
1037 virtual void SetUp() OVERRIDE { | |
1038 // Make sure the file manager actually gets loaded. | |
1039 ComponentLoader::EnableBackgroundExtensionsForTesting(); | |
1040 PlatformAppBrowserTest::SetUp(); | |
1041 } | |
1042 | |
1043 // ShellWindowRegistry::Observer implementation. | |
1044 virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE { | |
1045 opener_app_ids_.insert(shell_window->extension()->id()); | |
1046 } | |
1047 virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE {} | |
1048 virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE {} | |
1049 | |
1050 protected: | |
1051 // A set of ids of apps we've seen open a shell window. | |
1052 std::set<std::string> opener_app_ids_; | |
1053 }; | |
1054 | |
1055 IN_PROC_BROWSER_TEST_F(PlatformAppIncognitoBrowserTest, IncognitoComponentApp) { | |
1056 // Get the file manager app. | |
1057 const Extension* file_manager = extension_service()->GetExtensionById( | |
1058 "hhaomjibdihmijegdhdafkllkbggdgoj", false); | |
1059 ASSERT_TRUE(file_manager != NULL); | |
1060 Profile* incognito_profile = profile()->GetOffTheRecordProfile(); | |
1061 ASSERT_TRUE(incognito_profile != NULL); | |
1062 | |
1063 // Wait until the file manager has had a chance to register its listener | |
1064 // for the launch event. | |
1065 EventRouter* router = ExtensionSystem::Get(incognito_profile)->event_router(); | |
1066 ASSERT_TRUE(router != NULL); | |
1067 while (!router->ExtensionHasEventListener(file_manager->id(), | |
1068 event_names::kOnLaunched)) { | |
1069 content::RunAllPendingInMessageLoop(); | |
1070 } | |
1071 | |
1072 // Listen for new shell windows so we see the file manager app launch itself. | |
1073 ShellWindowRegistry* registry = ShellWindowRegistry::Get(incognito_profile); | |
1074 ASSERT_TRUE(registry != NULL); | |
1075 registry->AddObserver(this); | |
1076 | |
1077 chrome::AppLaunchParams params(incognito_profile, file_manager, 0); | |
1078 chrome::OpenApplication(params); | |
1079 | |
1080 while (!ContainsKey(opener_app_ids_, file_manager->id())) { | |
1081 content::RunAllPendingInMessageLoop(); | |
1082 } | |
1083 } | |
1084 | |
1085 #endif // defined(OS_CHROMEOS) | |
1086 | |
1087 | |
1088 } // namespace extensions | |
OLD | NEW |