Index: apps/launcher.cc |
diff --git a/apps/launcher.cc b/apps/launcher.cc |
index 52c1328889d46c66fcaae4536f8c002aeb27c1b2..5c7d16e7d1c4524f7d371ce86d8a9f3bcd352e01 100644 |
--- a/apps/launcher.cc |
+++ b/apps/launcher.cc |
@@ -91,7 +91,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 |
@@ -101,23 +101,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), |
@@ -150,9 +158,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); |
+ } else { |
+ ++it; |
+ } |
} |
BrowserThread::PostTask(BrowserThread::UI, |
@@ -160,10 +173,24 @@ class PlatformAppPathLauncher |
base::Bind(&PlatformAppPathLauncher::Launch, this)); |
} |
- void OnFileValid() { |
+ void OnFileValid() { StepToFillMimeTypes(); } |
+ |
+ void OnFileInvalid(const base::FilePath& /* error_path */) { |
+ LaunchWithNoLaunchData(); |
+ } |
+ |
+ void StepToFillMimeTypes() { |
+ 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 (drive::util::IsUnderDriveMountPoint(file_path_)) { |
- PlatformAppPathLauncher::GetMimeTypeAndLaunchForDriveFile(); |
+ if (drive::util::IsUnderDriveMountPoint(file_paths_[mime_types_.size()])) { |
+ GetMimeTypeForDriveFileAndStep(); |
return; |
} |
#endif |
@@ -171,51 +198,52 @@ 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); |
// 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_paths_[0]) || |
kinaba
2014/05/27 07:08:26
0 => mime_types.size() ? (I'd rather recommend you
hirono
2014/05/28 02:23:27
Done.
|
+ base::DirectoryExists(file_paths_[0])) { |
+ LOG(WARNING) << "No file exists with path " << file_paths_[0].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_paths_[0], &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_paths_[0], &content[0], content.size()); |
if (bytes_read >= 0) { |
net::SniffMimeType(&content[0], |
bytes_read, |
- net::FilePathToFileURL(file_path_), |
+ net::FilePathToFileURL(file_paths_[0]), |
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) |
- void GetMimeTypeAndLaunchForDriveFile() { |
+ void GetMimeTypeForDriveFileAndStep() { |
DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- drive::FileSystemInterface* file_system = |
+ drive::FileSystemInterface* const file_system = |
drive::util::GetFileSystemByProfile(profile_); |
if (!file_system) { |
LaunchWithNoLaunchData(); |
@@ -223,7 +251,7 @@ class PlatformAppPathLauncher |
} |
file_system->GetFile( |
- drive::util::ExtractDrivePath(file_path_), |
+ drive::util::ExtractDrivePath(file_paths_[mime_types_.size()]), |
base::Bind(&PlatformAppPathLauncher::OnGotDriveFile, this)); |
} |
@@ -240,7 +268,9 @@ class PlatformAppPathLauncher |
const std::string& mime_type = |
entry->file_specific_info().content_mime_type(); |
- LaunchWithMimeType(mime_type.empty() ? kFallbackMimeType : mime_type); |
+ mime_types_.push_back(mime_type.empty() ? kFallbackMimeType : mime_type); |
+ |
+ StepToFillMimeTypes(); |
} |
#endif // defined(OS_CHROMEOS) |
@@ -249,25 +279,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; |
} |
@@ -280,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::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) { |
// 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. |
@@ -323,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_; |
@@ -391,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); |
} |