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