summaryrefslogtreecommitdiffstats
path: root/apps/launcher.cc
diff options
context:
space:
mode:
authorhirono@chromium.org <hirono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-04 09:40:29 +0000
committerhirono@chromium.org <hirono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-04 09:40:29 +0000
commit3113a232cc1ca764298b3eca4e062d10982c2672 (patch)
treee2ff0c2f53e6b28e977fe74f753016fd7c22b6b9 /apps/launcher.cc
parentc2b43dbac2d7feff547cf7e1caf0689b713d6195 (diff)
downloadchromium_src-3113a232cc1ca764298b3eca4e062d10982c2672.zip
chromium_src-3113a232cc1ca764298b3eca4e062d10982c2672.tar.gz
chromium_src-3113a232cc1ca764298b3eca4e062d10982c2672.tar.bz2
Files.app: Let Files.app pass mutliple files to file handlers.
Previously if multiple files are selected for launching a file handler, Files.app sends multiple launch events for each file. But according to the specification of the launch event, we can put multiple entries in a single launch event. This CL lets Files.app follow the specificaiton. BUG=358694 TEST=manually R=benwells@chromium.org, kinaba@chromium.org Review URL: https://codereview.chromium.org/300063006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274755 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'apps/launcher.cc')
-rw-r--r--apps/launcher.cc245
1 files changed, 162 insertions, 83 deletions
diff --git a/apps/launcher.cc b/apps/launcher.cc
index f357881..8cfbee9 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_);
PrepareFilesForWritableApp(
- 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,149 @@ 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;
- }
-#endif
-
+ GetNextNonNativeMimeType();
+#else
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
- base::Bind(&PlatformAppPathLauncher::GetMimeTypeAndLaunch, this));
+ base::Bind(&PlatformAppPathLauncher::GetMimeTypesAndLaunch, this));
+#endif
}
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) {
+ 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 +330,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 +378,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 +447,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);
}