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 50using apps::ShellWindow; 51using apps::ShellWindowRegistry; 52using content::WebContents; 53using web_modal::WebContentsModalDialogManager; 54 55namespace extensions { 56 57namespace { 58 59// Non-abstract RenderViewContextMenu class. 60class 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. 83class 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 111bool 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 125const 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. 132IN_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. 139IN_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. 145IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisabledWindowProperties) { 146 ASSERT_TRUE(RunPlatformAppTest("platform_apps/disabled_window_properties")) 147 << message_; 148} 149 150IN_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 172IN_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 199IN_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 226IN_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 254IN_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 282IN_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 308IN_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 322IN_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. 328IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowStorage) { 329 ASSERT_TRUE(RunPlatformAppTest("platform_apps/storage")) << message_; 330} 331 332IN_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 338IN_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. 343IN_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. 349IN_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 386IN_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. 431IN_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. 441IN_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. 470IN_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. 478IN_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 "". 487IN_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 "". 496IN_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 *. 510IN_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 *. 526IN_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 *. 535IN_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. 544IN_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. 552IN_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. 560IN_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. 568IN_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. 576IN_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. 583IN_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. 590IN_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 598IN_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. 606IN_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 614IN_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 624IN_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 637IN_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 649IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, 650 MAYBE_ShellWindowRestoreState) { 651 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restore_state")); 652} 653 654IN_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 730namespace { 731 732class 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 742void 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 797IN_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 812IN_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 826IN_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. 851IN_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 865namespace { 866 867// Simple observer to check for NOTIFICATION_EXTENSION_INSTALLED events to 868// ensure installation does or does not occur in certain scenarios. 869class 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. 900IN_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. 930IN_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. 971IN_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 999IN_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 1014IN_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 1029class 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 1055IN_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 1089