diff options
author | benwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-11 12:20:17 +0000 |
---|---|---|
committer | benwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-11 12:20:17 +0000 |
commit | 7b9faeb78d74cab7464edbd9fe4abf7f6fc9d976 (patch) | |
tree | 48af523ca6128173b876296b1852ccfc264be3fb | |
parent | 9f0ebb6594e76046aa661acdda3aff45dd729c60 (diff) | |
download | chromium_src-7b9faeb78d74cab7464edbd9fe4abf7f6fc9d976.zip chromium_src-7b9faeb78d74cab7464edbd9fe4abf7f6fc9d976.tar.gz chromium_src-7b9faeb78d74cab7464edbd9fe4abf7f6fc9d976.tar.bz2 |
Pass command line arguments through with --load-and-launch-app.
This lets uninstalled unpacked apps be started via this flag and passed
files to process.
BUG=246510
Review URL: https://chromiumcodereview.appspot.com/16357005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205503 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | apps/app_load_service.cc | 56 | ||||
-rw-r--r-- | apps/app_load_service.h | 28 | ||||
-rw-r--r-- | apps/load_and_launch_browsertest.cc | 43 | ||||
-rw-r--r-- | chrome/browser/ui/startup/startup_browser_creator.cc | 11 | ||||
-rw-r--r-- | chrome/test/data/extensions/platform_apps/load_and_launch_file/manifest.json | 20 | ||||
-rw-r--r-- | chrome/test/data/extensions/platform_apps/load_and_launch_file/test.js | 30 |
6 files changed, 156 insertions, 32 deletions
diff --git a/apps/app_load_service.cc b/apps/app_load_service.cc index 1d78554..f3d45e1 100644 --- a/apps/app_load_service.cc +++ b/apps/app_load_service.cc @@ -10,6 +10,8 @@ #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/extensions/platform_app_launcher.h" #include "chrome/browser/extensions/shell_window_registry.h" +#include "chrome/browser/extensions/unpacked_installer.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" @@ -20,17 +22,12 @@ using extensions::Extension; using extensions::ExtensionPrefs; -namespace { - -enum PostReloadAction { - RELOAD_ACTION_LAUNCH, - RELOAD_ACTION_RESTART, -}; - -} // namespace - namespace apps { +AppLoadService::PostReloadAction::PostReloadAction() + : command_line(CommandLine::NO_PROGRAM) { +} + AppLoadService::AppLoadService(Profile* profile) : profile_(profile) { registrar_.Add( @@ -44,15 +41,28 @@ AppLoadService::AppLoadService(Profile* profile) AppLoadService::~AppLoadService() {} void AppLoadService::RestartApplication(const std::string& extension_id) { - reload_actions_[extension_id] = RELOAD_ACTION_RESTART; + post_reload_actions_[extension_id].action_type = RESTART; ExtensionService* service = extensions::ExtensionSystem::Get(profile_)-> extension_service(); DCHECK(service); service->ReloadExtension(extension_id); } -void AppLoadService::ScheduleLaunchOnLoad(const std::string& extension_id) { - reload_actions_[extension_id] = RELOAD_ACTION_LAUNCH; +bool AppLoadService::LoadAndLaunch(const base::FilePath& extension_path, + const CommandLine& command_line, + const base::FilePath& current_dir) { + std::string extension_id; + if (!extensions::UnpackedInstaller::Create(profile_->GetExtensionService())-> + LoadFromCommandLine(base::FilePath(extension_path), &extension_id)) { + return false; + } + + // Schedule the app to be launched once loaded. + PostReloadAction& action = post_reload_actions_[extension_id]; + action.action_type = LAUNCH_WITH_COMMAND_LINE; + action.command_line = command_line; + action.current_dir = current_dir; + return true; } // static @@ -66,23 +76,28 @@ void AppLoadService::Observe(int type, switch (type) { case chrome::NOTIFICATION_EXTENSION_LOADED: { const Extension* extension = content::Details<Extension>(details).ptr(); - std::map<std::string, int>::iterator it = reload_actions_.find( - extension->id()); - if (it == reload_actions_.end()) + std::map<std::string, PostReloadAction>::iterator it = + post_reload_actions_.find(extension->id()); + if (it == post_reload_actions_.end()) break; - switch (it->second) { - case RELOAD_ACTION_LAUNCH: + switch (it->second.action_type) { + case LAUNCH: extensions::LaunchPlatformApp(profile_, extension); break; - case RELOAD_ACTION_RESTART: + case RESTART: extensions::RestartPlatformApp(profile_, extension); break; + case LAUNCH_WITH_COMMAND_LINE: + extensions::LaunchPlatformAppWithCommandLine( + profile_, extension, &it->second.command_line, + it->second.current_dir); + break; default: NOTREACHED(); } - reload_actions_.erase(it); + post_reload_actions_.erase(it); break; } case chrome::NOTIFICATION_EXTENSION_UNLOADED: { @@ -97,7 +112,8 @@ void AppLoadService::Observe(int type, Extension::DISABLE_RELOAD) && !extensions::ShellWindowRegistry::Get(profile_)-> GetShellWindowsForApp(unload_info->extension->id()).empty()) { - reload_actions_[unload_info->extension->id()] = RELOAD_ACTION_LAUNCH; + post_reload_actions_[unload_info->extension->id()].action_type = + LAUNCH; } } break; diff --git a/apps/app_load_service.h b/apps/app_load_service.h index c7e75c6..5c16804 100644 --- a/apps/app_load_service.h +++ b/apps/app_load_service.h @@ -8,6 +8,8 @@ #include <map> #include <string> +#include "base/command_line.h" +#include "base/files/file_path.h" #include "components/browser_context_keyed_service/browser_context_keyed_service.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -21,6 +23,20 @@ namespace apps { class AppLoadService : public BrowserContextKeyedService, public content::NotificationObserver { public: + enum PostReloadActionType { + LAUNCH, + RESTART, + LAUNCH_WITH_COMMAND_LINE, + }; + + struct PostReloadAction { + PostReloadAction(); + + PostReloadActionType action_type; + CommandLine command_line; + base::FilePath current_dir; + }; + explicit AppLoadService(Profile* profile); virtual ~AppLoadService(); @@ -28,9 +44,13 @@ class AppLoadService : public BrowserContextKeyedService, // event. void RestartApplication(const std::string& extension_id); - // Schedule a launch to happen for the extension with id |extension_id| - // when it loads next. This does not cause the extension to be reloaded. - void ScheduleLaunchOnLoad(const std::string& extension_id); + // Loads (or reloads) the app with |extension_path|, then launches it. Any + // command line parameters from |command_line| will be passed along via + // launch parameters. Returns true if loading the extension has begun + // successfully. + bool LoadAndLaunch(const base::FilePath& extension_path, + const CommandLine& command_line, + const base::FilePath& current_dir); static AppLoadService* Get(Profile* profile); @@ -42,7 +62,7 @@ class AppLoadService : public BrowserContextKeyedService, // Map of extension id to reload action. Absence from the map implies // no action. - std::map<std::string, int> reload_actions_; + std::map<std::string, PostReloadAction> post_reload_actions_; content::NotificationRegistrar registrar_; Profile* profile_; diff --git a/apps/load_and_launch_browsertest.cc b/apps/load_and_launch_browsertest.cc index 63d2266..fd0f2dd 100644 --- a/apps/load_and_launch_browsertest.cc +++ b/apps/load_and_launch_browsertest.cc @@ -58,6 +58,49 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, process, TestTimeouts::action_timeout())); } +// TODO(jackhou): Enable this test once it works on OSX. It currently does not +// work for the same reason --app-id doesn't. See http://crbug.com/148465 +#if defined(OS_MACOSX) +#define MAYBE_LoadAndLaunchAppWithFile DISABLED_LoadAndLaunchAppWithFile +#else +#define MAYBE_LoadAndLaunchAppWithFile LoadAndLaunchAppWithFile +#endif + +IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, + MAYBE_LoadAndLaunchAppWithFile) { + ExtensionTestMessageListener launched_listener("Launched", false); + + const CommandLine& cmdline = *CommandLine::ForCurrentProcess(); + CommandLine new_cmdline(cmdline.GetProgram()); + + const char* kSwitchNames[] = { + switches::kUserDataDir, + }; + new_cmdline.CopySwitchesFrom(cmdline, kSwitchNames, arraysize(kSwitchNames)); + + base::FilePath app_path = test_data_dir_ + .AppendASCII("platform_apps") + .AppendASCII("load_and_launch_file"); + + base::FilePath test_file_path = test_data_dir_ + .AppendASCII("platform_apps") + .AppendASCII("launch_files") + .AppendASCII("test.txt"); + + new_cmdline.AppendSwitchNative(apps::kLoadAndLaunchApp, + app_path.value()); + new_cmdline.AppendSwitch(content::kLaunchAsBrowser); + new_cmdline.AppendArgPath(test_file_path); + + base::ProcessHandle process; + base::LaunchProcess(new_cmdline, base::LaunchOptions(), &process); + ASSERT_NE(base::kNullProcessHandle, process); + + ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); + ASSERT_TRUE(base::WaitForSingleProcess( + process, TestTimeouts::action_timeout())); +} + namespace { // TestFixture that appends --load-and-launch-app before calling BrowserMain. diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index db6644a..e64f900 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc @@ -622,17 +622,12 @@ bool StartupBrowserCreator::ProcessCmdLineImpl( command_line, last_used_profile->GetPrefs())) { CommandLine::StringType path = command_line.GetSwitchValueNative( apps::kLoadAndLaunchApp); - std::string extension_id; - if (!extensions::UnpackedInstaller::Create( - last_used_profile->GetExtensionService())-> - LoadFromCommandLine(base::FilePath(path), &extension_id)) { + + if (!apps::AppLoadService::Get(last_used_profile)->LoadAndLaunch( + base::FilePath(path), command_line, cur_dir)) { return false; } - // Schedule the app to be launched once loaded. - apps::AppLoadService::Get(last_used_profile)->ScheduleLaunchOnLoad( - extension_id); - // Return early here since we don't want to open a browser window. // The exception is when there are no browser windows, since we don't want // chrome to shut down. diff --git a/chrome/test/data/extensions/platform_apps/load_and_launch_file/manifest.json b/chrome/test/data/extensions/platform_apps/load_and_launch_file/manifest.json new file mode 100644 index 0000000..24ec215 --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/load_and_launch_file/manifest.json @@ -0,0 +1,20 @@ +{ + "name": "Platform App Launch Test", + "version": "1", + "file_handlers": { + "text": { + "types": [ + "text/*" + ], + "title": "Test editor" + } + }, + "app": { + "background": { + "scripts": ["test.js"] + } + }, + "permissions": [ + "fileSystem" + ] +} diff --git a/chrome/test/data/extensions/platform_apps/load_and_launch_file/test.js b/chrome/test/data/extensions/platform_apps/load_and_launch_file/test.js new file mode 100644 index 0000000..fa60a7b --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/load_and_launch_file/test.js @@ -0,0 +1,30 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +chrome.app.runtime.onLaunched.addListener(function (launchData) { + // Test that the id and items fields in FileEntry can be read. + chrome.test.runTests([ + function testFileHandler() { + chrome.test.assertFalse(!launchData, "No launchData"); + chrome.test.assertEq(launchData.id, "text", + "launchData.id incorrect"); + chrome.test.assertEq(launchData.items.length, 1); + chrome.test.assertTrue( + chrome.fileSystem.retainEntry(launchData.items[0].entry) != null); + + launchData.items[0].entry.file(function(file) { + var reader = new FileReader(); + reader.onloadend = function(e) { + chrome.test.assertEq( + reader.result.indexOf("This is a test. Word."), 0); + chrome.test.sendMessage('Launched'); + }; + reader.onerror = function(e) { + chrome.test.fail("Error reading file contents."); + }; + reader.readAsText(file); + }); + } + ]); +}); |