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