Index: apps/launcher.cc |
diff --git a/apps/launcher.cc b/apps/launcher.cc |
index acaec4156a77cf2b3005a097fab7065cf4ec475b..5612d9e5069fc2330fa77475be015481185348b9 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,17 @@ 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(); |
+ ++it) { |
+ if (!DoMakePathAbsolute(current_directory, &*it)) { |
+ LOG(WARNING) << "Cannot make absolute path from " << it->value(); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&PlatformAppPathLauncher::LaunchWithNoLaunchData, this)); |
+ return; |
+ } |
} |
BrowserThread::PostTask(BrowserThread::UI, |
@@ -159,93 +175,146 @@ class PlatformAppPathLauncher |
} |
void OnFileValid() { |
+ mime_types_.resize(file_paths_.size()); |
#if defined(OS_CHROMEOS) |
- if (file_manager::util::IsUnderNonNativeLocalPath(profile_, file_path_)) { |
- file_manager::util::GetNonNativeLocalPathMimeType( |
- profile_, |
- file_path_, |
- base::Bind(&PlatformAppPathLauncher::OnGotMimeType, this)); |
- return; |
- } |
+ GetNextNonNativeMimeType(); |
+#else |
+ GetMimeTypesAndLaunch(); |
#endif |
- |
- BrowserThread::PostTask( |
- BrowserThread::FILE, |
- FROM_HERE, |
- base::Bind(&PlatformAppPathLauncher::GetMimeTypeAndLaunch, this)); |
} |
void OnFileInvalid(const base::FilePath& /* error_path */) { |
LaunchWithNoLaunchData(); |
} |
- void GetMimeTypeAndLaunch() { |
- DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
+#if defined(OS_CHROMEOS) |
+ void GetNextNonNativeMimeType() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- // 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)); |
- return; |
+ bool any_native_files = false; |
+ for (size_t i = 0; i < mime_types_.size(); ++i) { |
+ if (!mime_types_[i].empty()) |
+ continue; |
+ const base::FilePath& file_path = file_paths_[i]; |
+ if (file_manager::util::IsUnderNonNativeLocalPath(profile_, file_path)) { |
+ file_manager::util::GetNonNativeLocalPathMimeType( |
+ profile_, |
+ file_path, |
+ base::Bind(&PlatformAppPathLauncher::OnGotMimeType, this, i)); |
+ return; |
+ } |
+ any_native_files = true; |
} |
- std::string 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()); |
- if (bytes_read >= 0) { |
- net::SniffMimeType(&content[0], |
- bytes_read, |
- net::FilePathToFileURL(file_path_), |
- std::string(), // type_hint (passes no hint) |
- &mime_type); |
- } |
- if (mime_type.empty()) |
- mime_type = kFallbackMimeType; |
+ // If there are any native files, we need to call GetMimeTypesAndLaunch to |
+ // obtain mime types for the files. |
+ if (!any_native_files) { |
benwells
2014/06/02 23:11:29
Shouldn't this be if (any_native_files)?
hirono
2014/06/03 06:42:14
Done.
|
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind(&PlatformAppPathLauncher::GetMimeTypesAndLaunch, this)); |
+ return; |
} |
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
- &PlatformAppPathLauncher::LaunchWithMimeType, this, mime_type)); |
+ // Otherwise, we can call LaunchWithMimeTypes directly. |
+ LaunchWithMimeTypes(); |
} |
-#if defined(OS_CHROMEOS) |
- void OnGotMimeType(bool success, const std::string& mime_type) { |
+ void OnGotMimeType(size_t index, bool success, const std::string& mime_type) { |
if (!success) { |
LaunchWithNoLaunchData(); |
return; |
} |
- LaunchWithMimeType(mime_type.empty() ? kFallbackMimeType : mime_type); |
+ mime_types_[index] = mime_type.empty() ? kFallbackMimeType : mime_type; |
+ GetNextNonNativeMimeType(); |
} |
#endif |
+ void GetMimeTypesAndLaunch() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
+ |
+ for (size_t i = 0; i < mime_types_.size(); ++i) { |
+ if (!this->mime_types_[i].empty()) |
+ continue; |
+ const base::FilePath& file_path = file_paths_[i]; |
+ |
+ // 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)); |
+ return; |
+ } |
+ |
+ std::string 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()); |
+ if (bytes_read >= 0) { |
+ net::SniffMimeType(&content[0], |
+ bytes_read, |
+ net::FilePathToFileURL(file_path), |
+ std::string(), // type_hint (passes no hint) |
+ &mime_type); |
+ } |
+ if (mime_type.empty()) |
+ mime_type = kFallbackMimeType; |
+ } |
+ mime_types_[i] = mime_type; |
+ } |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&PlatformAppPathLauncher::LaunchWithMimeTypes, this)); |
+ } |
+ |
void LaunchWithNoLaunchData() { |
// This method is required as an entry point on the UI thread. |
LaunchPlatformAppWithNoData(profile_, extension_); |
} |
- void LaunchWithMimeType(const std::string& mime_type) { |
+ void LaunchWithMimeTypes() { |
+ 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 +327,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::GrantAccessToFilesAndLaunch, |
+ 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); |
+ GrantAccessToFilesAndLaunch(host); |
} |
- void GrantAccessToFileAndLaunch(const std::string& mime_type, |
- ExtensionHost* host) { |
+ void GrantAccessToFilesAndLaunch(ExtensionHost* host) { |
// 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 +375,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 +444,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); |
} |