Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: apps/launcher.cc

Issue 277873002: Use file thread when converting paths to absolute when loading apps. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Feedback Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "apps/launcher.h" 5 #include "apps/launcher.h"
6 6
7 #include "apps/browser/api/app_runtime/app_runtime_api.h" 7 #include "apps/browser/api/app_runtime/app_runtime_api.h"
8 #include "apps/browser/file_handler_util.h" 8 #include "apps/browser/file_handler_util.h"
9 #include "apps/common/api/app_runtime.h" 9 #include "apps/common/api/app_runtime.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 using extensions::Extension; 56 using extensions::Extension;
57 using extensions::ExtensionHost; 57 using extensions::ExtensionHost;
58 using extensions::ExtensionSystem; 58 using extensions::ExtensionSystem;
59 59
60 namespace apps { 60 namespace apps {
61 61
62 namespace { 62 namespace {
63 63
64 const char kFallbackMimeType[] = "application/octet-stream"; 64 const char kFallbackMimeType[] = "application/octet-stream";
65 65
66 bool MakePathAbsolute(const base::FilePath& current_directory, 66 bool DoMakePathAbsolute(const base::FilePath& current_directory,
67 base::FilePath* file_path) { 67 base::FilePath* file_path) {
68 DCHECK(file_path); 68 DCHECK(file_path);
69 if (file_path->IsAbsolute()) 69 if (file_path->IsAbsolute())
70 return true; 70 return true;
71 71
72 if (current_directory.empty()) { 72 if (current_directory.empty()) {
73 *file_path = base::MakeAbsoluteFilePath(*file_path); 73 *file_path = base::MakeAbsoluteFilePath(*file_path);
74 return !file_path->empty(); 74 return !file_path->empty();
75 } 75 }
76 76
77 if (!current_directory.IsAbsolute()) 77 if (!current_directory.IsAbsolute())
78 return false; 78 return false;
79 79
80 *file_path = current_directory.Append(*file_path); 80 *file_path = current_directory.Append(*file_path);
81 return true; 81 return true;
82 } 82 }
83 83
84 bool GetAbsolutePathFromCommandLine(const CommandLine& command_line,
85 const base::FilePath& current_directory,
86 base::FilePath* path) {
87 if (!command_line.GetArgs().size())
88 return false;
89
90 base::FilePath relative_path(command_line.GetArgs()[0]);
91 base::FilePath absolute_path(relative_path);
92 if (!MakePathAbsolute(current_directory, &absolute_path)) {
93 LOG(WARNING) << "Cannot make absolute path from " << relative_path.value();
94 return false;
95 }
96 *path = absolute_path;
97 return true;
98 }
99
100 // Helper method to launch the platform app |extension| with no data. This 84 // Helper method to launch the platform app |extension| with no data. This
101 // should be called in the fallback case, where it has been impossible to 85 // should be called in the fallback case, where it has been impossible to
102 // load or obtain file launch data. 86 // load or obtain file launch data.
103 void LaunchPlatformAppWithNoData(Profile* profile, const Extension* extension) { 87 void LaunchPlatformAppWithNoData(Profile* profile, const Extension* extension) {
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 88 DCHECK_CURRENTLY_ON(BrowserThread::UI);
105 AppEventRouter::DispatchOnLaunchedEvent(profile, extension); 89 AppEventRouter::DispatchOnLaunchedEvent(profile, extension);
106 } 90 }
107 91
108 // Class to handle launching of platform apps to open a specific path. 92 // Class to handle launching of platform apps to open a specific path.
109 // An instance of this class is created for each launch. The lifetime of these 93 // An instance of this class is created for each launch. The lifetime of these
110 // instances is managed by reference counted pointers. As long as an instance 94 // instances is managed by reference counted pointers. As long as an instance
111 // has outstanding tasks on a message queue it will be retained; once all 95 // has outstanding tasks on a message queue it will be retained; once all
112 // outstanding tasks are completed it will be deleted. 96 // outstanding tasks are completed it will be deleted.
113 class PlatformAppPathLauncher 97 class PlatformAppPathLauncher
114 : public base::RefCountedThreadSafe<PlatformAppPathLauncher> { 98 : public base::RefCountedThreadSafe<PlatformAppPathLauncher> {
115 public: 99 public:
116 PlatformAppPathLauncher(Profile* profile, 100 PlatformAppPathLauncher(Profile* profile,
117 const Extension* extension, 101 const Extension* extension,
118 const base::FilePath& file_path) 102 const base::FilePath& file_path)
119 : profile_(profile), extension_(extension), file_path_(file_path) {} 103 : profile_(profile), extension_(extension), file_path_(file_path) {}
120 104
121 void Launch() { 105 void Launch() {
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 106 DCHECK_CURRENTLY_ON(BrowserThread::UI);
123 if (file_path_.empty()) { 107 if (file_path_.empty()) {
124 LaunchPlatformAppWithNoData(profile_, extension_); 108 LaunchPlatformAppWithNoData(profile_, extension_);
125 return; 109 return;
126 } 110 }
127 111
128 DCHECK(file_path_.IsAbsolute()); 112 DCHECK(file_path_.IsAbsolute());
129 113
130 if (HasFileSystemWritePermission(extension_)) { 114 if (HasFileSystemWritePermission(extension_)) {
131 std::vector<base::FilePath> paths; 115 std::vector<base::FilePath> paths;
132 paths.push_back(file_path_); 116 paths.push_back(file_path_);
133 CheckWritableFiles( 117 CheckWritableFiles(
134 paths, 118 paths,
135 profile_, 119 profile_,
136 false, 120 false,
137 base::Bind(&PlatformAppPathLauncher::OnFileValid, this), 121 base::Bind(&PlatformAppPathLauncher::OnFileValid, this),
138 base::Bind(&PlatformAppPathLauncher::OnFileInvalid, this)); 122 base::Bind(&PlatformAppPathLauncher::OnFileInvalid, this));
139 return; 123 return;
140 } 124 }
141 125
142 OnFileValid(); 126 OnFileValid();
143 } 127 }
144 128
145 void LaunchWithHandler(const std::string& handler_id) { 129 void LaunchWithHandler(const std::string& handler_id) {
146 handler_id_ = handler_id; 130 handler_id_ = handler_id;
147 Launch(); 131 Launch();
148 } 132 }
149 133
134 void LaunchWithRelativePath(const base::FilePath& current_directory) {
135 BrowserThread::PostTask(
136 BrowserThread::FILE,
137 FROM_HERE,
138 base::Bind(&PlatformAppPathLauncher::MakePathAbsolute,
139 this,
140 current_directory));
141 }
142
150 private: 143 private:
151 friend class base::RefCountedThreadSafe<PlatformAppPathLauncher>; 144 friend class base::RefCountedThreadSafe<PlatformAppPathLauncher>;
152 145
153 virtual ~PlatformAppPathLauncher() {} 146 virtual ~PlatformAppPathLauncher() {}
154 147
148 void MakePathAbsolute(const base::FilePath& current_directory) {
149 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
150
151 if (!DoMakePathAbsolute(current_directory, &file_path_)) {
152 LOG(WARNING) << "Cannot make absolute path from " << file_path_.value();
153 file_path_ = base::FilePath();
154 }
155
156 BrowserThread::PostTask(BrowserThread::UI,
157 FROM_HERE,
158 base::Bind(&PlatformAppPathLauncher::Launch, this));
159 }
160
155 void OnFileValid() { 161 void OnFileValid() {
156 #if defined(OS_CHROMEOS) 162 #if defined(OS_CHROMEOS)
157 if (drive::util::IsUnderDriveMountPoint(file_path_)) { 163 if (drive::util::IsUnderDriveMountPoint(file_path_)) {
158 PlatformAppPathLauncher::GetMimeTypeAndLaunchForDriveFile(); 164 PlatformAppPathLauncher::GetMimeTypeAndLaunchForDriveFile();
159 return; 165 return;
160 } 166 }
161 #endif 167 #endif
162 168
163 BrowserThread::PostTask( 169 BrowserThread::PostTask(
164 BrowserThread::FILE, 170 BrowserThread::FILE,
165 FROM_HERE, 171 FROM_HERE,
166 base::Bind(&PlatformAppPathLauncher::GetMimeTypeAndLaunch, this)); 172 base::Bind(&PlatformAppPathLauncher::GetMimeTypeAndLaunch, this));
167 } 173 }
168 174
169 void OnFileInvalid(const base::FilePath& /* error_path */) { 175 void OnFileInvalid(const base::FilePath& /* error_path */) {
170 LaunchWithNoLaunchData(); 176 LaunchWithNoLaunchData();
171 } 177 }
172 178
173 void GetMimeTypeAndLaunch() { 179 void GetMimeTypeAndLaunch() {
174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 180 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
175 181
176 // If the file doesn't exist, or is a directory, launch with no launch data. 182 // If the file doesn't exist, or is a directory, launch with no launch data.
177 if (!base::PathExists(file_path_) || 183 if (!base::PathExists(file_path_) ||
178 base::DirectoryExists(file_path_)) { 184 base::DirectoryExists(file_path_)) {
179 LOG(WARNING) << "No file exists with path " << file_path_.value(); 185 LOG(WARNING) << "No file exists with path " << file_path_.value();
180 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( 186 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
181 &PlatformAppPathLauncher::LaunchWithNoLaunchData, this)); 187 &PlatformAppPathLauncher::LaunchWithNoLaunchData, this));
182 return; 188 return;
183 } 189 }
184 190
(...skipping 13 matching lines...) Expand all
198 if (mime_type.empty()) 204 if (mime_type.empty())
199 mime_type = kFallbackMimeType; 205 mime_type = kFallbackMimeType;
200 } 206 }
201 207
202 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( 208 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
203 &PlatformAppPathLauncher::LaunchWithMimeType, this, mime_type)); 209 &PlatformAppPathLauncher::LaunchWithMimeType, this, mime_type));
204 } 210 }
205 211
206 #if defined(OS_CHROMEOS) 212 #if defined(OS_CHROMEOS)
207 void GetMimeTypeAndLaunchForDriveFile() { 213 void GetMimeTypeAndLaunchForDriveFile() {
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 214 DCHECK_CURRENTLY_ON(BrowserThread::UI);
209 215
210 drive::FileSystemInterface* file_system = 216 drive::FileSystemInterface* file_system =
211 drive::util::GetFileSystemByProfile(profile_); 217 drive::util::GetFileSystemByProfile(profile_);
212 if (!file_system) { 218 if (!file_system) {
213 LaunchWithNoLaunchData(); 219 LaunchWithNoLaunchData();
214 return; 220 return;
215 } 221 }
216 222
217 file_system->GetFile( 223 file_system->GetFile(
218 drive::util::ExtractDrivePath(file_path_), 224 drive::util::ExtractDrivePath(file_path_),
219 base::Bind(&PlatformAppPathLauncher::OnGotDriveFile, this)); 225 base::Bind(&PlatformAppPathLauncher::OnGotDriveFile, this));
220 } 226 }
221 227
222 void OnGotDriveFile(drive::FileError error, 228 void OnGotDriveFile(drive::FileError error,
223 const base::FilePath& file_path, 229 const base::FilePath& file_path,
224 scoped_ptr<drive::ResourceEntry> entry) { 230 scoped_ptr<drive::ResourceEntry> entry) {
225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 231 DCHECK_CURRENTLY_ON(BrowserThread::UI);
226 232
227 if (error != drive::FILE_ERROR_OK || 233 if (error != drive::FILE_ERROR_OK ||
228 !entry || entry->file_specific_info().is_hosted_document()) { 234 !entry || entry->file_specific_info().is_hosted_document()) {
229 LaunchWithNoLaunchData(); 235 LaunchWithNoLaunchData();
230 return; 236 return;
231 } 237 }
232 238
233 const std::string& mime_type = 239 const std::string& mime_type =
234 entry->file_specific_info().content_mime_type(); 240 entry->file_specific_info().content_mime_type();
235 LaunchWithMimeType(mime_type.empty() ? kFallbackMimeType : mime_type); 241 LaunchWithMimeType(mime_type.empty() ? kFallbackMimeType : mime_type);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 host->render_process_host()->GetID(), 309 host->render_process_host()->GetID(),
304 file_path_, 310 file_path_,
305 false); 311 false);
306 AppEventRouter::DispatchOnLaunchedEventWithFileEntry( 312 AppEventRouter::DispatchOnLaunchedEventWithFileEntry(
307 profile_, extension_, handler_id_, mime_type, file_entry); 313 profile_, extension_, handler_id_, mime_type, file_entry);
308 } 314 }
309 315
310 // The profile the app should be run in. 316 // The profile the app should be run in.
311 Profile* profile_; 317 Profile* profile_;
312 // The extension providing the app. 318 // The extension providing the app.
319 // TODO(benwells): Hold onto the extension ID instead of a pointer as it
320 // is possible the extension will be unloaded while we're doing our thing.
321 // See http://crbug.com/372270 for details.
313 const Extension* extension_; 322 const Extension* extension_;
314 // The path to be passed through to the app. 323 // The path to be passed through to the app.
315 const base::FilePath file_path_; 324 base::FilePath file_path_;
316 // The ID of the file handler used to launch the app. 325 // The ID of the file handler used to launch the app.
317 std::string handler_id_; 326 std::string handler_id_;
318 327
319 DISALLOW_COPY_AND_ASSIGN(PlatformAppPathLauncher); 328 DISALLOW_COPY_AND_ASSIGN(PlatformAppPathLauncher);
320 }; 329 };
321 330
322 } // namespace 331 } // namespace
323 332
324 void LaunchPlatformAppWithCommandLine(Profile* profile, 333 void LaunchPlatformAppWithCommandLine(Profile* profile,
325 const Extension* extension, 334 const Extension* extension,
326 const CommandLine& command_line, 335 const CommandLine& command_line,
327 const base::FilePath& current_directory) { 336 const base::FilePath& current_directory) {
328 // An app with "kiosk_only" should not be installed and launched 337 // An app with "kiosk_only" should not be installed and launched
329 // outside of ChromeOS kiosk mode in the first place. This is a defensive 338 // outside of ChromeOS kiosk mode in the first place. This is a defensive
330 // check in case this scenario does occur. 339 // check in case this scenario does occur.
331 if (extensions::KioskModeInfo::IsKioskOnly(extension)) { 340 if (extensions::KioskModeInfo::IsKioskOnly(extension)) {
332 bool in_kiosk_mode = false; 341 bool in_kiosk_mode = false;
333 #if defined(OS_CHROMEOS) 342 #if defined(OS_CHROMEOS)
334 chromeos::UserManager* user_manager = chromeos::UserManager::Get(); 343 chromeos::UserManager* user_manager = chromeos::UserManager::Get();
335 in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp(); 344 in_kiosk_mode = user_manager && user_manager->IsLoggedInAsKioskApp();
336 #endif 345 #endif
337 if (!in_kiosk_mode) { 346 if (!in_kiosk_mode) {
338 LOG(ERROR) << "App with 'kiosk_only' attribute must be run in " 347 LOG(ERROR) << "App with 'kiosk_only' attribute must be run in "
339 << " ChromeOS kiosk mode."; 348 << " ChromeOS kiosk mode.";
340 NOTREACHED(); 349 NOTREACHED();
341 return; 350 return;
342 } 351 }
343 } 352 }
344 353
345 base::FilePath path; 354 if (command_line.GetArgs().empty()) {
346 if (!GetAbsolutePathFromCommandLine(command_line, current_directory, &path)) {
347 LaunchPlatformAppWithNoData(profile, extension); 355 LaunchPlatformAppWithNoData(profile, extension);
348 return; 356 return;
349 } 357 }
350 358
351 // TODO(benwells): add a command-line argument to provide a handler ID. 359 base::FilePath file_path(command_line.GetArgs()[0]);
352 LaunchPlatformAppWithPath(profile, extension, path); 360 scoped_refptr<PlatformAppPathLauncher> launcher =
361 new PlatformAppPathLauncher(profile, extension, file_path);
362 launcher->LaunchWithRelativePath(current_directory);
353 } 363 }
354 364
355 void LaunchPlatformAppWithPath(Profile* profile, 365 void LaunchPlatformAppWithPath(Profile* profile,
356 const Extension* extension, 366 const Extension* extension,
357 const base::FilePath& file_path) { 367 const base::FilePath& file_path) {
358 // launcher will be freed when nothing has a reference to it. The message
359 // queue will retain a reference for any outstanding task, so when the
360 // launcher has finished it will be freed.
361 scoped_refptr<PlatformAppPathLauncher> launcher = 368 scoped_refptr<PlatformAppPathLauncher> launcher =
362 new PlatformAppPathLauncher(profile, extension, file_path); 369 new PlatformAppPathLauncher(profile, extension, file_path);
363 launcher->Launch(); 370 launcher->Launch();
364 } 371 }
365 372
366 void LaunchPlatformApp(Profile* profile, const Extension* extension) { 373 void LaunchPlatformApp(Profile* profile, const Extension* extension) {
367 LaunchPlatformAppWithCommandLine(profile, 374 LaunchPlatformAppWithCommandLine(profile,
368 extension, 375 extension,
369 CommandLine(CommandLine::NO_PROGRAM), 376 CommandLine(CommandLine::NO_PROGRAM),
370 base::FilePath()); 377 base::FilePath());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 void LaunchPlatformAppWithUrl(Profile* profile, 412 void LaunchPlatformAppWithUrl(Profile* profile,
406 const Extension* extension, 413 const Extension* extension,
407 const std::string& handler_id, 414 const std::string& handler_id,
408 const GURL& url, 415 const GURL& url,
409 const GURL& referrer_url) { 416 const GURL& referrer_url) {
410 AppEventRouter::DispatchOnLaunchedEventWithUrl( 417 AppEventRouter::DispatchOnLaunchedEventWithUrl(
411 profile, extension, handler_id, url, referrer_url); 418 profile, extension, handler_id, url, referrer_url);
412 } 419 }
413 420
414 } // namespace apps 421 } // namespace apps
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698