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 59using content::WebContents; 60using web_modal::WebContentsModalDialogManager; 61 62namespace app_runtime = extensions::core_api::app_runtime; 63 64namespace extensions { 65 66namespace { 67 68// Non-abstract RenderViewContextMenu class. 69class 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. 90class 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) 119class 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) 177bool 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) 193const 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. 201IN_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. 208IN_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. 214IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisabledWindowProperties) { 215 ASSERT_TRUE(RunPlatformAppTest("platform_apps/disabled_window_properties")) 216 << message_; 217} 218 219IN_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 238IN_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 262IN_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 291IN_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 316IN_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 341IN_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 371IN_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 391IN_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. 397IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowStorage) { 398 ASSERT_TRUE(RunPlatformAppTest("platform_apps/storage")) << message_; 399} 400 401IN_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. 406IN_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. 412IN_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 449IN_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. 488IN_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. 498IN_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. 527IN_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. 535IN_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. 552IN_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 "". 561IN_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 "". 570IN_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 *. 584IN_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 *. 600IN_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 *. 609IN_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. 618IN_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. 626IN_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. 634IN_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. 642IN_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. 650IN_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. 658IN_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. 665IN_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. 672IN_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 680IN_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. 688IN_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. 696IN_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 707IN_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 717IN_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 728IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_AppWindowRestoreState) { 729 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restore_state")); 730} 731 732IN_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 807namespace { 808 809class 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 819void 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 865IN_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 880IN_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 894IN_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. 919IN_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 933namespace { 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. 938class 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. 970IN_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. 998IN_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. 1035IN_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 1055IN_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 1097IN_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 1112IN_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 1133IN_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. 1141IN_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 1159IN_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 1179class 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 1203IN_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 1233class 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. 1285IN_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. 1305IN_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