summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-11 12:20:17 +0000
committerbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-11 12:20:17 +0000
commit7b9faeb78d74cab7464edbd9fe4abf7f6fc9d976 (patch)
tree48af523ca6128173b876296b1852ccfc264be3fb
parent9f0ebb6594e76046aa661acdda3aff45dd729c60 (diff)
downloadchromium_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.cc56
-rw-r--r--apps/app_load_service.h28
-rw-r--r--apps/load_and_launch_browsertest.cc43
-rw-r--r--chrome/browser/ui/startup/startup_browser_creator.cc11
-rw-r--r--chrome/test/data/extensions/platform_apps/load_and_launch_file/manifest.json20
-rw-r--r--chrome/test/data/extensions/platform_apps/load_and_launch_file/test.js30
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);
+ });
+ }
+ ]);
+});