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