blob: 7d700a6f224ecb3382c2cdd9629287c77221769c [file] [log] [blame]
[email protected]24c81d692013-08-07 14:09:481// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]12e540452012-05-26 07:09:362// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]24c81d692013-08-07 14:09:485#include "apps/launcher.h"
[email protected]12e540452012-05-26 07:09:366
7#include "base/command_line.h"
[email protected]12e540452012-05-26 07:09:368#include "base/file_util.h"
[email protected]57999812013-02-24 05:40:529#include "base/files/file_path.h"
[email protected]12e540452012-05-26 07:09:3610#include "base/logging.h"
11#include "base/memory/ref_counted.h"
[email protected]46acbf12013-06-10 18:43:4212#include "base/strings/string_util.h"
[email protected]112158af2013-06-07 23:46:1813#include "base/strings/utf_string_conversions.h"
[email protected]e3b19382013-01-12 03:58:1414#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
[email protected]fc2a40f2013-03-13 13:14:5715#include "chrome/browser/extensions/api/file_system/file_system_api.h"
[email protected]12e540452012-05-26 07:09:3616#include "chrome/browser/profiles/profile.h"
[email protected]12e540452012-05-26 07:09:3617#include "content/public/browser/browser_thread.h"
[email protected]12e540452012-05-26 07:09:3618#include "content/public/browser/render_process_host.h"
[email protected]a6db6122012-09-03 06:00:2319#include "content/public/browser/web_contents.h"
[email protected]4c35abc2014-05-14 02:13:5820#include "content/public/common/content_switches.h"
21#include "content/public/common/url_constants.h"
[email protected]ce5f1b32014-06-22 01:46:4522#include "extensions/browser/api/app_runtime/app_runtime_api.h"
[email protected]34423532013-11-21 18:13:1023#include "extensions/browser/event_router.h"
[email protected]22401dc2014-03-21 01:38:5724#include "extensions/browser/extension_host.h"
[email protected]489db0842014-01-22 18:20:0325#include "extensions/browser/extension_prefs.h"
[email protected]59b0e602014-01-30 00:41:2426#include "extensions/browser/extension_system.h"
[email protected]ce5f1b32014-06-22 01:46:4527#include "extensions/browser/granted_file_entry.h"
[email protected]9fe42042013-10-29 21:13:3328#include "extensions/browser/lazy_background_task_queue.h"
[email protected]98b6d942013-11-10 00:34:0729#include "extensions/browser/process_manager.h"
[email protected]ce5f1b32014-06-22 01:46:4530#include "extensions/common/api/app_runtime.h"
[email protected]e4452d32013-11-15 23:07:4131#include "extensions/common/extension.h"
[email protected]fb820c02014-03-13 15:07:0832#include "extensions/common/extension_messages.h"
[email protected]70c39bb2013-11-26 22:59:2833#include "extensions/common/manifest_handlers/kiosk_mode_info.h"
[email protected]f7fc72c2014-04-22 13:01:5234#include "net/base/filename_util.h"
35#include "net/base/mime_sniffer.h"
[email protected]12e540452012-05-26 07:09:3636#include "net/base/mime_util.h"
37#include "net/base/net_util.h"
[email protected]43197ea22013-09-10 15:31:5638#include "url/gurl.h"
[email protected]12e540452012-05-26 07:09:3639
[email protected]906ae212013-03-24 01:37:1340#if defined(OS_CHROMEOS)
[email protected]3576d462014-05-29 01:50:2841#include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
[email protected]83d82d42014-05-16 02:04:4242#include "chrome/browser/chromeos/login/users/user_manager.h"
[email protected]906ae212013-03-24 01:37:1343#endif
44
[email protected]ce5f1b32014-06-22 01:46:4545namespace app_runtime = extensions::core_api::app_runtime;
[email protected]e054ea12013-08-20 00:41:5746
[email protected]12e540452012-05-26 07:09:3647using content::BrowserThread;
[email protected]ce5f1b32014-06-22 01:46:4548using extensions::AppRuntimeEventRouter;
[email protected]fc2a40f2013-03-13 13:14:5749using extensions::app_file_handler_util::CreateFileEntry;
[email protected]ce5f1b32014-06-22 01:46:4550using extensions::app_file_handler_util::FileHandlerCanHandleFile;
51using extensions::app_file_handler_util::FileHandlerForId;
52using extensions::app_file_handler_util::FirstFileHandlerForFile;
[email protected]ffb87062013-08-29 10:02:2553using extensions::app_file_handler_util::HasFileSystemWritePermission;
[email protected]ce5f1b32014-06-22 01:46:4554using extensions::app_file_handler_util::PrepareFilesForWritableApp;
[email protected]3a368a22014-03-26 19:29:1955using extensions::EventRouter;
[email protected]24c81d692013-08-07 14:09:4856using extensions::Extension;
57using extensions::ExtensionHost;
58using extensions::ExtensionSystem;
[email protected]ce5f1b32014-06-22 01:46:4559using extensions::GrantedFileEntry;
[email protected]d9ede582012-08-14 19:21:3860
[email protected]24c81d692013-08-07 14:09:4861namespace apps {
[email protected]12e540452012-05-26 07:09:3662
63namespace {
64
[email protected]9be0bad2013-04-18 05:51:3665const char kFallbackMimeType[] = "application/octet-stream";
66
[email protected]3567d142014-05-12 11:49:4367bool DoMakePathAbsolute(const base::FilePath& current_directory,
68 base::FilePath* file_path) {
[email protected]a5a0be02012-07-18 05:51:5469 DCHECK(file_path);
70 if (file_path->IsAbsolute())
71 return true;
72
[email protected]15476932013-04-12 05:17:1573 if (current_directory.empty()) {
74 *file_path = base::MakeAbsoluteFilePath(*file_path);
75 return !file_path->empty();
76 }
[email protected]a5a0be02012-07-18 05:51:5477
78 if (!current_directory.IsAbsolute())
79 return false;
80
81 *file_path = current_directory.Append(*file_path);
82 return true;
83}
84
[email protected]a228c842012-09-04 10:07:0585// Helper method to launch the platform app |extension| with no data. This
86// should be called in the fallback case, where it has been impossible to
87// load or obtain file launch data.
88void LaunchPlatformAppWithNoData(Profile* profile, const Extension* extension) {
[email protected]3567d142014-05-12 11:49:4389 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]ce5f1b32014-06-22 01:46:4590 AppRuntimeEventRouter::DispatchOnLaunchedEvent(profile, extension);
[email protected]a228c842012-09-04 10:07:0591}
92
[email protected]3113a232014-06-04 09:40:2993// Class to handle launching of platform apps to open specific paths.
[email protected]4e04f1e2012-06-20 03:20:3194// An instance of this class is created for each launch. The lifetime of these
95// instances is managed by reference counted pointers. As long as an instance
96// has outstanding tasks on a message queue it will be retained; once all
97// outstanding tasks are completed it will be deleted.
[email protected]a228c842012-09-04 10:07:0598class PlatformAppPathLauncher
99 : public base::RefCountedThreadSafe<PlatformAppPathLauncher> {
[email protected]12e540452012-05-26 07:09:36100 public:
[email protected]a228c842012-09-04 10:07:05101 PlatformAppPathLauncher(Profile* profile,
102 const Extension* extension,
[email protected]3113a232014-06-04 09:40:29103 const std::vector<base::FilePath>& file_paths)
104 : profile_(profile), extension_(extension), file_paths_(file_paths) {}
105
106 PlatformAppPathLauncher(Profile* profile,
107 const Extension* extension,
[email protected]650b2d52013-02-10 03:41:45108 const base::FilePath& file_path)
[email protected]3113a232014-06-04 09:40:29109 : profile_(profile), extension_(extension) {
110 if (!file_path.empty())
111 file_paths_.push_back(file_path);
112 }
[email protected]12e540452012-05-26 07:09:36113
114 void Launch() {
[email protected]3567d142014-05-12 11:49:43115 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]3113a232014-06-04 09:40:29116 if (file_paths_.empty()) {
[email protected]a228c842012-09-04 10:07:05117 LaunchPlatformAppWithNoData(profile_, extension_);
[email protected]12e540452012-05-26 07:09:36118 return;
119 }
120
[email protected]3113a232014-06-04 09:40:29121 for (size_t i = 0; i < file_paths_.size(); ++i) {
122 DCHECK(file_paths_[i].IsAbsolute());
123 }
[email protected]906ae212013-03-24 01:37:13124
[email protected]ffb87062013-08-29 10:02:25125 if (HasFileSystemWritePermission(extension_)) {
[email protected]07aa825a2014-06-03 12:39:32126 PrepareFilesForWritableApp(
[email protected]3113a232014-06-04 09:40:29127 file_paths_,
[email protected]ffb87062013-08-29 10:02:25128 profile_,
[email protected]6b7ecdd2013-08-29 14:16:24129 false,
[email protected]ffb87062013-08-29 10:02:25130 base::Bind(&PlatformAppPathLauncher::OnFileValid, this),
131 base::Bind(&PlatformAppPathLauncher::OnFileInvalid, this));
[email protected]906ae212013-03-24 01:37:13132 return;
133 }
[email protected]906ae212013-03-24 01:37:13134
[email protected]ffb87062013-08-29 10:02:25135 OnFileValid();
[email protected]12e540452012-05-26 07:09:36136 }
137
[email protected]af8dc08e2012-11-22 01:58:42138 void LaunchWithHandler(const std::string& handler_id) {
139 handler_id_ = handler_id;
140 Launch();
141 }
142
[email protected]3567d142014-05-12 11:49:43143 void LaunchWithRelativePath(const base::FilePath& current_directory) {
144 BrowserThread::PostTask(
145 BrowserThread::FILE,
146 FROM_HERE,
147 base::Bind(&PlatformAppPathLauncher::MakePathAbsolute,
148 this,
149 current_directory));
150 }
151
[email protected]12e540452012-05-26 07:09:36152 private:
[email protected]a228c842012-09-04 10:07:05153 friend class base::RefCountedThreadSafe<PlatformAppPathLauncher>;
[email protected]12e540452012-05-26 07:09:36154
[email protected]a228c842012-09-04 10:07:05155 virtual ~PlatformAppPathLauncher() {}
[email protected]12e540452012-05-26 07:09:36156
[email protected]3567d142014-05-12 11:49:43157 void MakePathAbsolute(const base::FilePath& current_directory) {
158 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
159
[email protected]3113a232014-06-04 09:40:29160 for (std::vector<base::FilePath>::iterator it = file_paths_.begin();
161 it != file_paths_.end();
162 ++it) {
163 if (!DoMakePathAbsolute(current_directory, &*it)) {
164 LOG(WARNING) << "Cannot make absolute path from " << it->value();
165 BrowserThread::PostTask(
166 BrowserThread::UI,
167 FROM_HERE,
168 base::Bind(&PlatformAppPathLauncher::LaunchWithNoLaunchData, this));
169 return;
170 }
[email protected]3567d142014-05-12 11:49:43171 }
172
173 BrowserThread::PostTask(BrowserThread::UI,
174 FROM_HERE,
175 base::Bind(&PlatformAppPathLauncher::Launch, this));
176 }
177
[email protected]ffb87062013-08-29 10:02:25178 void OnFileValid() {
[email protected]3113a232014-06-04 09:40:29179 mime_types_.resize(file_paths_.size());
[email protected]ffb87062013-08-29 10:02:25180#if defined(OS_CHROMEOS)
[email protected]3113a232014-06-04 09:40:29181 GetNextNonNativeMimeType();
182#else
[email protected]ffb87062013-08-29 10:02:25183 BrowserThread::PostTask(
184 BrowserThread::FILE,
185 FROM_HERE,
[email protected]3113a232014-06-04 09:40:29186 base::Bind(&PlatformAppPathLauncher::GetMimeTypesAndLaunch, this));
187#endif
[email protected]ffb87062013-08-29 10:02:25188 }
189
190 void OnFileInvalid(const base::FilePath& /* error_path */) {
191 LaunchWithNoLaunchData();
192 }
193
[email protected]3113a232014-06-04 09:40:29194#if defined(OS_CHROMEOS)
195 void GetNextNonNativeMimeType() {
196 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]12e540452012-05-26 07:09:36197
[email protected]3113a232014-06-04 09:40:29198 bool any_native_files = false;
199 for (size_t i = 0; i < mime_types_.size(); ++i) {
200 if (!mime_types_[i].empty())
201 continue;
202 const base::FilePath& file_path = file_paths_[i];
203 if (file_manager::util::IsUnderNonNativeLocalPath(profile_, file_path)) {
204 file_manager::util::GetNonNativeLocalPathMimeType(
205 profile_,
206 file_path,
207 base::Bind(&PlatformAppPathLauncher::OnGotMimeType, this, i));
208 return;
209 }
210 any_native_files = true;
211 }
212
213 // If there are any native files, we need to call GetMimeTypesAndLaunch to
214 // obtain mime types for the files.
215 if (any_native_files) {
216 BrowserThread::PostTask(
217 BrowserThread::FILE,
218 FROM_HERE,
219 base::Bind(&PlatformAppPathLauncher::GetMimeTypesAndLaunch, this));
[email protected]12e540452012-05-26 07:09:36220 return;
221 }
222
[email protected]3113a232014-06-04 09:40:29223 // Otherwise, we can call LaunchWithMimeTypes directly.
224 LaunchWithMimeTypes();
[email protected]12e540452012-05-26 07:09:36225 }
226
[email protected]3113a232014-06-04 09:40:29227 void OnGotMimeType(size_t index, bool success, const std::string& mime_type) {
[email protected]3576d462014-05-29 01:50:28228 if (!success) {
[email protected]906ae212013-03-24 01:37:13229 LaunchWithNoLaunchData();
230 return;
231 }
[email protected]3113a232014-06-04 09:40:29232 mime_types_[index] = mime_type.empty() ? kFallbackMimeType : mime_type;
233 GetNextNonNativeMimeType();
[email protected]906ae212013-03-24 01:37:13234 }
[email protected]3576d462014-05-29 01:50:28235#endif
[email protected]906ae212013-03-24 01:37:13236
[email protected]3113a232014-06-04 09:40:29237 void GetMimeTypesAndLaunch() {
238 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
239
240 for (size_t i = 0; i < mime_types_.size(); ++i) {
241 if (!this->mime_types_[i].empty())
242 continue;
243 const base::FilePath& file_path = file_paths_[i];
244
245 // If the file doesn't exist, or is a directory, launch with no launch
246 // data.
247 if (!base::PathExists(file_path) || base::DirectoryExists(file_path)) {
248 LOG(WARNING) << "No file exists with path " << file_path.value();
249 BrowserThread::PostTask(
250 BrowserThread::UI,
251 FROM_HERE,
252 base::Bind(&PlatformAppPathLauncher::LaunchWithNoLaunchData, this));
253 return;
254 }
255
256 std::string mime_type;
257 if (!net::GetMimeTypeFromFile(file_path, &mime_type)) {
258 // If MIME type of the file can't be determined by its path,
259 // try to sniff it by its content.
260 std::vector<char> content(net::kMaxBytesToSniff);
261 int bytes_read = base::ReadFile(file_path, &content[0], content.size());
262 if (bytes_read >= 0) {
263 net::SniffMimeType(&content[0],
264 bytes_read,
265 net::FilePathToFileURL(file_path),
266 std::string(), // type_hint (passes no hint)
267 &mime_type);
268 }
269 if (mime_type.empty())
270 mime_type = kFallbackMimeType;
271 }
272 mime_types_[i] = mime_type;
273 }
274
275 BrowserThread::PostTask(
276 BrowserThread::UI,
277 FROM_HERE,
278 base::Bind(&PlatformAppPathLauncher::LaunchWithMimeTypes, this));
279 }
280
[email protected]a228c842012-09-04 10:07:05281 void LaunchWithNoLaunchData() {
282 // This method is required as an entry point on the UI thread.
283 LaunchPlatformAppWithNoData(profile_, extension_);
284 }
285
[email protected]3113a232014-06-04 09:40:29286 void LaunchWithMimeTypes() {
287 DCHECK(file_paths_.size() == mime_types_.size());
288
[email protected]8427a0622013-02-11 17:00:57289 // Find file handler from the platform app for the file being opened.
[email protected]24c81d692013-08-07 14:09:48290 const extensions::FileHandlerInfo* handler = NULL;
[email protected]3113a232014-06-04 09:40:29291 if (!handler_id_.empty()) {
[email protected]af8dc08e2012-11-22 01:58:42292 handler = FileHandlerForId(*extension_, handler_id_);
[email protected]3113a232014-06-04 09:40:29293 if (handler) {
294 for (size_t i = 0; i < file_paths_.size(); ++i) {
295 if (!FileHandlerCanHandleFile(
296 *handler, mime_types_[i], file_paths_[i])) {
297 LOG(WARNING)
298 << "Extension does not provide a valid file handler for "
299 << file_paths_[i].value();
300 handler = NULL;
301 break;
302 }
303 }
304 }
305 } else {
306 std::set<std::pair<base::FilePath, std::string> > path_and_file_type_set;
307 for (size_t i = 0; i < file_paths_.size(); ++i) {
308 path_and_file_type_set.insert(
309 std::make_pair(file_paths_[i], mime_types_[i]));
310 }
311 const std::vector<const extensions::FileHandlerInfo*>& handlers =
312 extensions::app_file_handler_util::FindFileHandlersForFiles(
313 *extension_, path_and_file_type_set);
314 if (!handlers.empty())
315 handler = handlers[0];
[email protected]af8dc08e2012-11-22 01:58:42316 }
[email protected]af8dc08e2012-11-22 01:58:42317
[email protected]8427a0622013-02-11 17:00:57318 // If this app doesn't have a file handler that supports the file, launch
319 // with no launch data.
320 if (!handler) {
[email protected]3113a232014-06-04 09:40:29321 LOG(WARNING) << "Extension does not provide a valid file handler.";
[email protected]12e540452012-05-26 07:09:36322 LaunchWithNoLaunchData();
323 return;
324 }
325
[email protected]56573d72013-05-09 06:36:37326 if (handler_id_.empty())
327 handler_id_ = handler->id;
328
[email protected]4e04f1e2012-06-20 03:20:31329 // Access needs to be granted to the file for the process associated with
330 // the extension. To do this the ExtensionHost is needed. This might not be
[email protected]12e540452012-05-26 07:09:36331 // available, or it might be in the process of being unloaded, in which case
[email protected]4e04f1e2012-06-20 03:20:31332 // the lazy background task queue is used to load the extension and then
[email protected]12e540452012-05-26 07:09:36333 // call back to us.
[email protected]3113a232014-06-04 09:40:29334 extensions::LazyBackgroundTaskQueue* const queue =
[email protected]12e540452012-05-26 07:09:36335 ExtensionSystem::Get(profile_)->lazy_background_task_queue();
336 if (queue->ShouldEnqueueTask(profile_, extension_)) {
[email protected]3113a232014-06-04 09:40:29337 queue->AddPendingTask(
338 profile_,
339 extension_->id(),
340 base::Bind(&PlatformAppPathLauncher::GrantAccessToFilesAndLaunch,
341 this));
[email protected]12e540452012-05-26 07:09:36342 return;
343 }
344
[email protected]3113a232014-06-04 09:40:29345 extensions::ProcessManager* const process_manager =
[email protected]12e540452012-05-26 07:09:36346 ExtensionSystem::Get(profile_)->process_manager();
[email protected]3113a232014-06-04 09:40:29347 ExtensionHost* const host =
[email protected]4e04f1e2012-06-20 03:20:31348 process_manager->GetBackgroundHostForExtension(extension_->id());
[email protected]12e540452012-05-26 07:09:36349 DCHECK(host);
[email protected]3113a232014-06-04 09:40:29350 GrantAccessToFilesAndLaunch(host);
[email protected]12e540452012-05-26 07:09:36351 }
352
[email protected]3113a232014-06-04 09:40:29353 void GrantAccessToFilesAndLaunch(ExtensionHost* host) {
[email protected]12e540452012-05-26 07:09:36354 // If there was an error loading the app page, |host| will be NULL.
355 if (!host) {
356 LOG(ERROR) << "Could not load app page for " << extension_->id();
357 return;
358 }
359
[email protected]3113a232014-06-04 09:40:29360 std::vector<GrantedFileEntry> file_entries;
361 for (size_t i = 0; i < file_paths_.size(); ++i) {
362 file_entries.push_back(
363 CreateFileEntry(profile_,
364 extension_,
365 host->render_process_host()->GetID(),
366 file_paths_[i],
367 false));
368 }
369
[email protected]ce5f1b32014-06-22 01:46:45370 AppRuntimeEventRouter::DispatchOnLaunchedEventWithFileEntries(
[email protected]3113a232014-06-04 09:40:29371 profile_, extension_, handler_id_, mime_types_, file_entries);
[email protected]12e540452012-05-26 07:09:36372 }
373
[email protected]4e04f1e2012-06-20 03:20:31374 // The profile the app should be run in.
[email protected]12e540452012-05-26 07:09:36375 Profile* profile_;
[email protected]4e04f1e2012-06-20 03:20:31376 // The extension providing the app.
[email protected]3567d142014-05-12 11:49:43377 // TODO(benwells): Hold onto the extension ID instead of a pointer as it
378 // is possible the extension will be unloaded while we're doing our thing.
379 // See http://crbug.com/372270 for details.
[email protected]12e540452012-05-26 07:09:36380 const Extension* extension_;
[email protected]a228c842012-09-04 10:07:05381 // The path to be passed through to the app.
[email protected]3113a232014-06-04 09:40:29382 std::vector<base::FilePath> file_paths_;
383 std::vector<std::string> mime_types_;
[email protected]af8dc08e2012-11-22 01:58:42384 // The ID of the file handler used to launch the app.
385 std::string handler_id_;
[email protected]12e540452012-05-26 07:09:36386
[email protected]a228c842012-09-04 10:07:05387 DISALLOW_COPY_AND_ASSIGN(PlatformAppPathLauncher);
[email protected]4e04f1e2012-06-20 03:20:31388};
389
[email protected]12e540452012-05-26 07:09:36390} // namespace
391
[email protected]2a69b942013-05-31 09:37:53392void LaunchPlatformAppWithCommandLine(Profile* profile,
393 const Extension* extension,
[email protected]7d501ce2013-12-17 03:49:12394 const CommandLine& command_line,
[email protected]2a69b942013-05-31 09:37:53395 const base::FilePath& current_directory) {
[email protected]14a18bf2013-09-26 08:42:30396 // An app with "kiosk_only" should not be installed and launched
397 // outside of ChromeOS kiosk mode in the first place. This is a defensive
398 // check in case this scenario does occur.
399 if (extensions::KioskModeInfo::IsKioskOnly(extension)) {
400 bool in_kiosk_mode = false;
401#if defined(OS_CHROMEOS)
402 chromeos::UserManager* user_manager = chromeos::UserManager::Get();
403 in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp();
404#endif
405 if (!in_kiosk_mode) {
406 LOG(ERROR) << "App with 'kiosk_only' attribute must be run in "
407 << " ChromeOS kiosk mode.";
408 NOTREACHED();
[email protected]8a011172013-08-09 04:29:23409 return;
410 }
[email protected]14a18bf2013-09-26 08:42:30411 }
[email protected]8a011172013-08-09 04:29:23412
[email protected]4c35abc2014-05-14 02:13:58413#if defined(OS_WIN)
414 base::CommandLine::StringType about_blank_url(
[email protected]8e09c7af2014-06-10 11:46:17415 base::ASCIIToWide(url::kAboutBlankURL));
[email protected]4c35abc2014-05-14 02:13:58416#else
[email protected]8e09c7af2014-06-10 11:46:17417 base::CommandLine::StringType about_blank_url(url::kAboutBlankURL);
[email protected]4c35abc2014-05-14 02:13:58418#endif
419 CommandLine::StringVector args = command_line.GetArgs();
420 // Browser tests will add about:blank to the command line. This should
421 // never be interpreted as a file to open, as doing so with an app that
422 // has write access will result in a file 'about' being created, which
423 // causes problems on the bots.
424 if (args.empty() || (command_line.HasSwitch(switches::kTestType) &&
425 args[0] == about_blank_url)) {
[email protected]a228c842012-09-04 10:07:05426 LaunchPlatformAppWithNoData(profile, extension);
427 return;
428 }
429
[email protected]3567d142014-05-12 11:49:43430 base::FilePath file_path(command_line.GetArgs()[0]);
431 scoped_refptr<PlatformAppPathLauncher> launcher =
432 new PlatformAppPathLauncher(profile, extension, file_path);
433 launcher->LaunchWithRelativePath(current_directory);
[email protected]a228c842012-09-04 10:07:05434}
435
436void LaunchPlatformAppWithPath(Profile* profile,
437 const Extension* extension,
[email protected]650b2d52013-02-10 03:41:45438 const base::FilePath& file_path) {
[email protected]a228c842012-09-04 10:07:05439 scoped_refptr<PlatformAppPathLauncher> launcher =
440 new PlatformAppPathLauncher(profile, extension, file_path);
[email protected]12e540452012-05-26 07:09:36441 launcher->Launch();
442}
443
[email protected]2a69b942013-05-31 09:37:53444void LaunchPlatformApp(Profile* profile, const Extension* extension) {
[email protected]7d501ce2013-12-17 03:49:12445 LaunchPlatformAppWithCommandLine(profile,
446 extension,
447 CommandLine(CommandLine::NO_PROGRAM),
448 base::FilePath());
[email protected]2a69b942013-05-31 09:37:53449}
450
[email protected]3113a232014-06-04 09:40:29451void LaunchPlatformAppWithFileHandler(
452 Profile* profile,
453 const Extension* extension,
454 const std::string& handler_id,
455 const std::vector<base::FilePath>& file_paths) {
[email protected]af8dc08e2012-11-22 01:58:42456 scoped_refptr<PlatformAppPathLauncher> launcher =
[email protected]3113a232014-06-04 09:40:29457 new PlatformAppPathLauncher(profile, extension, file_paths);
[email protected]af8dc08e2012-11-22 01:58:42458 launcher->LaunchWithHandler(handler_id);
459}
460
[email protected]961745f2013-05-25 14:09:24461void RestartPlatformApp(Profile* profile, const Extension* extension) {
[email protected]3a368a22014-03-26 19:29:19462 EventRouter* event_router = EventRouter::Get(profile);
[email protected]c7c0c922014-01-09 00:03:36463 bool listening_to_restart = event_router->
464 ExtensionHasEventListener(extension->id(),
465 app_runtime::OnRestarted::kEventName);
[email protected]771c8d272013-05-17 09:47:40466
467 if (listening_to_restart) {
[email protected]ce5f1b32014-06-22 01:46:45468 AppRuntimeEventRouter::DispatchOnRestartedEvent(profile, extension);
[email protected]771c8d272013-05-17 09:47:40469 return;
470 }
471
[email protected]2d9f2a792014-01-24 12:44:09472 extensions::ExtensionPrefs* extension_prefs =
473 extensions::ExtensionPrefs::Get(profile);
[email protected]4b7111f22013-06-18 14:22:12474 bool had_windows = extension_prefs->IsActive(extension->id());
475 extension_prefs->SetIsActive(extension->id(), false);
[email protected]c7c0c922014-01-09 00:03:36476 bool listening_to_launch = event_router->
477 ExtensionHasEventListener(extension->id(),
478 app_runtime::OnLaunched::kEventName);
[email protected]771c8d272013-05-17 09:47:40479
480 if (listening_to_launch && had_windows)
481 LaunchPlatformAppWithNoData(profile, extension);
[email protected]fc2a40f2013-03-13 13:14:57482}
483
[email protected]43197ea22013-09-10 15:31:56484void LaunchPlatformAppWithUrl(Profile* profile,
485 const Extension* extension,
486 const std::string& handler_id,
487 const GURL& url,
488 const GURL& referrer_url) {
[email protected]ce5f1b32014-06-22 01:46:45489 AppRuntimeEventRouter::DispatchOnLaunchedEventWithUrl(
[email protected]43197ea22013-09-10 15:31:56490 profile, extension, handler_id, url, referrer_url);
491}
492
[email protected]24c81d692013-08-07 14:09:48493} // namespace apps