Index: apps/launcher.cc |
diff --git a/apps/launcher.cc b/apps/launcher.cc |
index 1c8c57fd072b15653598af2b7c9971c4e8ea9a15..4765c84e30de8caf40ec97268f7f1bbf20078c7f 100644 |
--- a/apps/launcher.cc |
+++ b/apps/launcher.cc |
@@ -89,7 +89,7 @@ void LaunchPlatformAppWithNoData(Profile* profile, const Extension* extension) { |
AppEventRouter::DispatchOnLaunchedEvent(profile, extension); |
} |
-// Class to handle launching of platform apps to open a specific path. |
+// Class to handle launching of platform apps to open specific paths. |
// An instance of this class is created for each launch. The lifetime of these |
// instances is managed by reference counted pointers. As long as an instance |
// has outstanding tasks on a message queue it will be retained; once all |
@@ -99,23 +99,31 @@ class PlatformAppPathLauncher |
public: |
PlatformAppPathLauncher(Profile* profile, |
const Extension* extension, |
+ const std::vector<base::FilePath>& file_paths) |
+ : profile_(profile), extension_(extension), file_paths_(file_paths) {} |
+ |
+ PlatformAppPathLauncher(Profile* profile, |
+ const Extension* extension, |
const base::FilePath& file_path) |
- : profile_(profile), extension_(extension), file_path_(file_path) {} |
+ : profile_(profile), extension_(extension) { |
+ if (!file_path.empty()) |
+ file_paths_.push_back(file_path); |
+ } |
void Launch() { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- if (file_path_.empty()) { |
+ if (file_paths_.empty()) { |
LaunchPlatformAppWithNoData(profile_, extension_); |
return; |
} |
- DCHECK(file_path_.IsAbsolute()); |
+ for (size_t i = 0; i < file_paths_.size(); ++i) { |
+ DCHECK(file_paths_[i].IsAbsolute()); |
+ } |
if (HasFileSystemWritePermission(extension_)) { |
- std::vector<base::FilePath> paths; |
- paths.push_back(file_path_); |
CheckWritableFiles( |
- paths, |
+ file_paths_, |
profile_, |
false, |
base::Bind(&PlatformAppPathLauncher::OnFileValid, this), |
@@ -148,9 +156,14 @@ class PlatformAppPathLauncher |
void MakePathAbsolute(const base::FilePath& current_directory) { |
DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
- if (!DoMakePathAbsolute(current_directory, &file_path_)) { |
- LOG(WARNING) << "Cannot make absolute path from " << file_path_.value(); |
- file_path_ = base::FilePath(); |
+ for (std::vector<base::FilePath>::iterator it = file_paths_.begin(); |
+ it != file_paths_.end();) { |
+ if (!DoMakePathAbsolute(current_directory, &*it)) { |
+ LOG(WARNING) << "Cannot make absolute path from " << it->value(); |
+ file_paths_.erase(it); |
benwells
2014/05/28 22:46:14
should this be it = file_path_.erase(it)?
I'd be
hirono
2014/05/29 04:08:03
Done.
|
+ } else { |
+ ++it; |
+ } |
} |
BrowserThread::PostTask(BrowserThread::UI, |
@@ -158,12 +171,27 @@ class PlatformAppPathLauncher |
base::Bind(&PlatformAppPathLauncher::Launch, this)); |
} |
- void OnFileValid() { |
+ void OnFileValid() { StepToFillMimeTypes(); } |
+ |
+ void OnFileInvalid(const base::FilePath& /* error_path */) { |
+ LaunchWithNoLaunchData(); |
+ } |
+ |
+ void StepToFillMimeTypes() { |
benwells
2014/05/28 22:46:14
This logic is more complicated than it needs to be
hirono
2014/05/29 04:08:03
Done.
|
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ DCHECK(file_paths_.size() >= mime_types_.size()); |
+ |
+ if (file_paths_.size() == mime_types_.size()) { |
+ LaunchWithMimeType(); |
+ return; |
+ } |
+ |
#if defined(OS_CHROMEOS) |
- if (file_manager::util::IsUnderSpecialPath(profile_, file_path_)) { |
+ if (file_manager::util::IsUnderSpecialPath( |
+ profile_, file_paths_[mime_types_.size()])) { |
file_manager::util::GetSpecialPathMimeType( |
profile_, |
- file_path_, |
+ file_paths_[mime_types_.size()], |
base::Bind(&PlatformAppPathLauncher::OnGotMimeType, this)); |
return; |
} |
@@ -172,44 +200,45 @@ class PlatformAppPathLauncher |
BrowserThread::PostTask( |
BrowserThread::FILE, |
FROM_HERE, |
- base::Bind(&PlatformAppPathLauncher::GetMimeTypeAndLaunch, this)); |
- } |
- |
- void OnFileInvalid(const base::FilePath& /* error_path */) { |
- LaunchWithNoLaunchData(); |
+ base::Bind(&PlatformAppPathLauncher::GetMimeTypeAndStep, this)); |
} |
- void GetMimeTypeAndLaunch() { |
+ void GetMimeTypeAndStep() { |
DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
+ const base::FilePath& file_path = file_paths_[mime_types_.size()]; |
+ |
// If the file doesn't exist, or is a directory, launch with no launch data. |
- if (!base::PathExists(file_path_) || |
- base::DirectoryExists(file_path_)) { |
- LOG(WARNING) << "No file exists with path " << file_path_.value(); |
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
- &PlatformAppPathLauncher::LaunchWithNoLaunchData, this)); |
+ if (!base::PathExists(file_path) || base::DirectoryExists(file_path)) { |
+ LOG(WARNING) << "No file exists with path " << file_path.value(); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&PlatformAppPathLauncher::LaunchWithNoLaunchData, this)); |
return; |
} |
std::string mime_type; |
- if (!net::GetMimeTypeFromFile(file_path_, &mime_type)) { |
+ if (!net::GetMimeTypeFromFile(file_path, &mime_type)) { |
// If MIME type of the file can't be determined by its path, |
// try to sniff it by its content. |
std::vector<char> content(net::kMaxBytesToSniff); |
- int bytes_read = base::ReadFile(file_path_, &content[0], content.size()); |
+ int bytes_read = base::ReadFile(file_path, &content[0], content.size()); |
if (bytes_read >= 0) { |
net::SniffMimeType(&content[0], |
bytes_read, |
- net::FilePathToFileURL(file_path_), |
+ net::FilePathToFileURL(file_path), |
std::string(), // type_hint (passes no hint) |
&mime_type); |
} |
if (mime_type.empty()) |
mime_type = kFallbackMimeType; |
} |
- |
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
- &PlatformAppPathLauncher::LaunchWithMimeType, this, mime_type)); |
+ mime_types_.push_back(mime_type); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&PlatformAppPathLauncher::StepToFillMimeTypes, this)); |
} |
#if defined(OS_CHROMEOS) |
@@ -218,7 +247,8 @@ class PlatformAppPathLauncher |
LaunchWithNoLaunchData(); |
return; |
} |
- LaunchWithMimeType(mime_type.empty() ? kFallbackMimeType : mime_type); |
+ mime_types_.push_back(mime_type.empty() ? kFallbackMimeType : mime_type); |
+ StepToFillMimeTypes(); |
} |
#endif |
@@ -227,25 +257,42 @@ class PlatformAppPathLauncher |
LaunchPlatformAppWithNoData(profile_, extension_); |
} |
- void LaunchWithMimeType(const std::string& mime_type) { |
+ void LaunchWithMimeType() { |
+ DCHECK(file_paths_.size() == mime_types_.size()); |
+ |
// Find file handler from the platform app for the file being opened. |
const extensions::FileHandlerInfo* handler = NULL; |
- if (!handler_id_.empty()) |
+ if (!handler_id_.empty()) { |
handler = FileHandlerForId(*extension_, handler_id_); |
- else |
- handler = FirstFileHandlerForFile(*extension_, mime_type, file_path_); |
- if (handler && !FileHandlerCanHandleFile(*handler, mime_type, file_path_)) { |
- LOG(WARNING) << "Extension does not provide a valid file handler for " |
- << file_path_.value(); |
- LaunchWithNoLaunchData(); |
- return; |
+ if (handler) { |
+ for (size_t i = 0; i < file_paths_.size(); ++i) { |
+ if (!FileHandlerCanHandleFile( |
+ *handler, mime_types_[i], file_paths_[i])) { |
+ LOG(WARNING) |
+ << "Extension does not provide a valid file handler for " |
+ << file_paths_[i].value(); |
+ handler = NULL; |
+ break; |
+ } |
+ } |
+ } |
+ } else { |
+ std::set<std::pair<base::FilePath, std::string> > path_and_file_type_set; |
+ for (size_t i = 0; i < file_paths_.size(); ++i) { |
+ path_and_file_type_set.insert( |
+ std::make_pair(file_paths_[i], mime_types_[i])); |
+ } |
+ const std::vector<const extensions::FileHandlerInfo*>& handlers = |
+ extensions::app_file_handler_util::FindFileHandlersForFiles( |
+ *extension_, path_and_file_type_set); |
+ if (!handlers.empty()) |
+ handler = handlers[0]; |
} |
// If this app doesn't have a file handler that supports the file, launch |
// with no launch data. |
if (!handler) { |
- LOG(WARNING) << "Extension does not provide a valid file handler for " |
- << file_path_.value(); |
+ LOG(WARNING) << "Extension does not provide a valid file handler."; |
LaunchWithNoLaunchData(); |
return; |
} |
@@ -258,39 +305,44 @@ class PlatformAppPathLauncher |
// available, or it might be in the process of being unloaded, in which case |
// the lazy background task queue is used to load the extension and then |
// call back to us. |
- extensions::LazyBackgroundTaskQueue* queue = |
+ extensions::LazyBackgroundTaskQueue* const queue = |
ExtensionSystem::Get(profile_)->lazy_background_task_queue(); |
if (queue->ShouldEnqueueTask(profile_, extension_)) { |
- queue->AddPendingTask(profile_, extension_->id(), base::Bind( |
- &PlatformAppPathLauncher::GrantAccessToFileAndLaunch, |
- this, mime_type)); |
+ queue->AddPendingTask( |
+ profile_, |
+ extension_->id(), |
+ base::Bind(&PlatformAppPathLauncher::GrantAccessToFileAndLaunch, |
+ this)); |
return; |
} |
- extensions::ProcessManager* process_manager = |
+ extensions::ProcessManager* const process_manager = |
ExtensionSystem::Get(profile_)->process_manager(); |
- ExtensionHost* host = |
+ ExtensionHost* const host = |
process_manager->GetBackgroundHostForExtension(extension_->id()); |
DCHECK(host); |
- GrantAccessToFileAndLaunch(mime_type, host); |
+ GrantAccessToFileAndLaunch(host); |
} |
- void GrantAccessToFileAndLaunch(const std::string& mime_type, |
- ExtensionHost* host) { |
+ void GrantAccessToFileAndLaunch(ExtensionHost* host) { |
benwells
2014/05/28 22:46:14
Nit should be GrantAccessToFilesAndLaunch
hirono
2014/05/29 04:08:03
Done.
|
// If there was an error loading the app page, |host| will be NULL. |
if (!host) { |
LOG(ERROR) << "Could not load app page for " << extension_->id(); |
return; |
} |
- GrantedFileEntry file_entry = |
- CreateFileEntry(profile_, |
- extension_, |
- host->render_process_host()->GetID(), |
- file_path_, |
- false); |
- AppEventRouter::DispatchOnLaunchedEventWithFileEntry( |
- profile_, extension_, handler_id_, mime_type, file_entry); |
+ std::vector<GrantedFileEntry> file_entries; |
+ for (size_t i = 0; i < file_paths_.size(); ++i) { |
+ file_entries.push_back( |
+ CreateFileEntry(profile_, |
+ extension_, |
+ host->render_process_host()->GetID(), |
+ file_paths_[i], |
+ false)); |
+ } |
+ |
+ AppEventRouter::DispatchOnLaunchedEventWithFileEntries( |
+ profile_, extension_, handler_id_, mime_types_, file_entries); |
} |
// The profile the app should be run in. |
@@ -301,7 +353,8 @@ class PlatformAppPathLauncher |
// See http://crbug.com/372270 for details. |
const Extension* extension_; |
// The path to be passed through to the app. |
- base::FilePath file_path_; |
+ std::vector<base::FilePath> file_paths_; |
+ std::vector<std::string> mime_types_; |
// The ID of the file handler used to launch the app. |
std::string handler_id_; |
@@ -369,12 +422,13 @@ void LaunchPlatformApp(Profile* profile, const Extension* extension) { |
base::FilePath()); |
} |
-void LaunchPlatformAppWithFileHandler(Profile* profile, |
- const Extension* extension, |
- const std::string& handler_id, |
- const base::FilePath& file_path) { |
+void LaunchPlatformAppWithFileHandler( |
+ Profile* profile, |
+ const Extension* extension, |
+ const std::string& handler_id, |
+ const std::vector<base::FilePath>& file_paths) { |
scoped_refptr<PlatformAppPathLauncher> launcher = |
- new PlatformAppPathLauncher(profile, extension, file_path); |
+ new PlatformAppPathLauncher(profile, extension, file_paths); |
launcher->LaunchWithHandler(handler_id); |
} |