Chromium Code Reviews| Index: chrome/browser/extensions/platform_app_launcher.cc |
| diff --git a/chrome/browser/extensions/platform_app_launcher.cc b/chrome/browser/extensions/platform_app_launcher.cc |
| index a208d89945370d6baa86b61764c860adbf9f9396..cbc0bd2709462c4f214bcfc96798309573a5082a 100644 |
| --- a/chrome/browser/extensions/platform_app_launcher.cc |
| +++ b/chrome/browser/extensions/platform_app_launcher.cc |
| @@ -16,6 +16,7 @@ |
| #include "chrome/browser/extensions/extension_process_manager.h" |
| #include "chrome/browser/extensions/extension_system.h" |
| #include "chrome/browser/extensions/lazy_background_task_queue.h" |
| +#include "chrome/browser/intents/web_intents_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/extensions/extension_messages.h" |
| @@ -35,8 +36,6 @@ namespace extensions { |
| namespace { |
| -const char kViewIntent[] = "http://webintents.org/view"; |
| - |
| bool MakePathAbsolute(const FilePath& current_directory, |
| FilePath* file_path) { |
| DCHECK(file_path); |
| @@ -53,84 +52,93 @@ bool MakePathAbsolute(const FilePath& current_directory, |
| return true; |
| } |
| -// Class to handle launching of platform apps with command line information. |
| +bool GetAbsolutePathFromCommandLine(const CommandLine* command_line, |
| + const FilePath& current_directory, |
| + FilePath* path) { |
| + if (!command_line || !command_line->GetArgs().size()) |
| + return false; |
| + |
| + FilePath relative_path(command_line->GetArgs()[0]); |
| + FilePath absolute_path(relative_path); |
| + if (!MakePathAbsolute(current_directory, &absolute_path)) { |
| + LOG(WARNING) << "Cannot make absolute path from " << relative_path.value(); |
| + return false; |
| + } |
| + *path = absolute_path; |
| + return true; |
| +} |
| + |
| +// Helper method to launches the platform app |extension| with no data. This |
| +// should be called in the fallback case for the launchers above. |
| +void LaunchPlatformAppWithNoData(Profile* profile, const Extension* extension) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + extensions::AppEventRouter::DispatchOnLaunchedEvent(profile, extension); |
| +} |
| + |
| +// Class to handle launching of platform apps to open a specific path. |
| // 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 |
| // outstanding tasks are completed it will be deleted. |
| -class PlatformAppCommandLineLauncher |
| - : public base::RefCountedThreadSafe<PlatformAppCommandLineLauncher> { |
| +class PlatformAppPathLauncher |
| + : public base::RefCountedThreadSafe<PlatformAppPathLauncher> { |
| public: |
| - PlatformAppCommandLineLauncher(Profile* profile, |
| - const Extension* extension, |
| - const CommandLine* command_line, |
| - const FilePath& current_directory) |
| + PlatformAppPathLauncher(Profile* profile, |
| + const Extension* extension, |
| + const FilePath& file_path) |
| : profile_(profile), |
| extension_(extension), |
| - command_line_(command_line), |
| - current_directory_(current_directory) {} |
| + file_path_(file_path) {} |
| void Launch() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - if (!command_line_ || !command_line_->GetArgs().size()) { |
| - LaunchWithNoLaunchData(); |
| + if (file_path_.empty()) { |
| + LaunchPlatformAppWithNoData(profile_, extension_); |
| return; |
| } |
| - FilePath file_path(command_line_->GetArgs()[0]); |
| + DCHECK(file_path_.IsAbsolute()); |
| BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( |
| - &PlatformAppCommandLineLauncher::GetMimeTypeAndLaunch, |
| - this, file_path)); |
| + &PlatformAppPathLauncher::GetMimeTypeAndLaunch, this)); |
| } |
| private: |
| - friend class base::RefCountedThreadSafe<PlatformAppCommandLineLauncher>; |
| + friend class base::RefCountedThreadSafe<PlatformAppPathLauncher>; |
| - virtual ~PlatformAppCommandLineLauncher() {} |
| + virtual ~PlatformAppPathLauncher() {} |
| - void LaunchWithNoLaunchData() { |
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| - extensions::AppEventRouter::DispatchOnLaunchedEvent(profile_, extension_); |
| - } |
| - |
| - void GetMimeTypeAndLaunch(const FilePath& file_path) { |
| + void GetMimeTypeAndLaunch() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| - // If we cannot construct an absolute path, launch with no launch data. |
| - FilePath absolute_path(file_path); |
| - if (!MakePathAbsolute(current_directory_, &absolute_path)) { |
| - LOG(WARNING) << "Cannot make absolute path from " << file_path.value(); |
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
| - &PlatformAppCommandLineLauncher::LaunchWithNoLaunchData, this)); |
| - return; |
| - } |
| - |
| // If the file doesn't exist, or is a directory, launch with no launch data. |
| - if (!file_util::PathExists(absolute_path) || |
| - file_util::DirectoryExists(absolute_path)) { |
| - LOG(WARNING) << "No file exists with path " << absolute_path.value(); |
| + if (!file_util::PathExists(file_path_) || |
| + file_util::DirectoryExists(file_path_)) { |
| + LOG(WARNING) << "No file exists with path " << file_path_.value(); |
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
| - &PlatformAppCommandLineLauncher::LaunchWithNoLaunchData, this)); |
| + &PlatformAppPathLauncher::LaunchWithNoLaunchData, this)); |
| return; |
| } |
| std::string mime_type; |
| // If we cannot obtain the MIME type, launch with no launch data. |
| - if (!net::GetMimeTypeFromFile(absolute_path, &mime_type)) { |
| + if (!net::GetMimeTypeFromFile(file_path_, &mime_type)) { |
| LOG(WARNING) << "Could not obtain MIME type for " |
| - << absolute_path.value(); |
| + << file_path_.value(); |
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
| - &PlatformAppCommandLineLauncher::LaunchWithNoLaunchData, this)); |
| + &PlatformAppPathLauncher::LaunchWithNoLaunchData, this)); |
| return; |
| } |
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
| - &PlatformAppCommandLineLauncher::LaunchWithMimeTypeAndPath, |
| - this, absolute_path, mime_type)); |
| + &PlatformAppPathLauncher::LaunchWithMimeType, this, mime_type)); |
| } |
| - void LaunchWithMimeTypeAndPath(const FilePath& file_path, |
| - const std::string& mime_type) { |
| + void LaunchWithNoLaunchData() { |
| + // This method is required as an entry point on the UI thread. |
| + LaunchPlatformAppWithNoData(profile_, extension_); |
| + } |
| + |
| + void LaunchWithMimeType(const std::string& mime_type) { |
| // Find the intent service from the platform app for the file being opened. |
| webkit_glue::WebIntentServiceData service; |
| bool found_service = false; |
| @@ -139,7 +147,7 @@ class PlatformAppCommandLineLauncher |
| extension_->intents_services(); |
| for (size_t i = 0; i < services.size(); i++) { |
| std::string service_type_ascii = UTF16ToASCII(services[i].type); |
| - if (services[i].action == ASCIIToUTF16(kViewIntent) && |
| + if (services[i].action == ASCIIToUTF16(web_intents::action::kView) && |
| net::MatchesMimeType(service_type_ascii, mime_type)) { |
| service = services[i]; |
| found_service = true; |
| @@ -151,7 +159,7 @@ class PlatformAppCommandLineLauncher |
| // no launch data. |
| if (!found_service) { |
| LOG(WARNING) << "Extension does not provide a valid intent for " |
| - << file_path.value(); |
| + << file_path_.value(); |
| LaunchWithNoLaunchData(); |
| return; |
| } |
| @@ -165,8 +173,8 @@ class PlatformAppCommandLineLauncher |
| ExtensionSystem::Get(profile_)->lazy_background_task_queue(); |
| if (queue->ShouldEnqueueTask(profile_, extension_)) { |
| queue->AddPendingTask(profile_, extension_->id(), base::Bind( |
| - &PlatformAppCommandLineLauncher::GrantAccessToFileAndLaunch, |
| - this, file_path, mime_type)); |
| + &PlatformAppPathLauncher::GrantAccessToFileAndLaunch, |
| + this, mime_type)); |
| return; |
| } |
| @@ -175,11 +183,10 @@ class PlatformAppCommandLineLauncher |
| extensions::ExtensionHost* host = |
| process_manager->GetBackgroundHostForExtension(extension_->id()); |
| DCHECK(host); |
| - GrantAccessToFileAndLaunch(file_path, mime_type, host); |
| + GrantAccessToFileAndLaunch(mime_type, host); |
| } |
| - void GrantAccessToFileAndLaunch(const FilePath& file_path, |
| - const std::string& mime_type, |
| + void GrantAccessToFileAndLaunch(const std::string& mime_type, |
| extensions::ExtensionHost* host) { |
| // If there was an error loading the app page, |host| will be NULL. |
| if (!host) { |
| @@ -195,34 +202,32 @@ class PlatformAppCommandLineLauncher |
| // If the renderer already has permission to read these paths, it is not |
| // regranted, as this would overwrite any other permissions which the |
| // renderer may already have. |
| - if (!policy->CanReadFile(renderer_id, file_path)) |
| - policy->GrantReadFile(renderer_id, file_path); |
| + if (!policy->CanReadFile(renderer_id, file_path_)) |
| + policy->GrantReadFile(renderer_id, file_path_); |
| std::string registered_name; |
| fileapi::IsolatedContext* isolated_context = |
| fileapi::IsolatedContext::GetInstance(); |
| DCHECK(isolated_context); |
| std::string filesystem_id = isolated_context->RegisterFileSystemForPath( |
| - fileapi::kFileSystemTypeNativeLocal, file_path, ®istered_name); |
| + fileapi::kFileSystemTypeNativeLocal, file_path_, ®istered_name); |
| // Granting read file system permission as well to allow file-system |
| // read operations. |
| policy->GrantReadFileSystem(renderer_id, filesystem_id); |
| extensions::AppEventRouter::DispatchOnLaunchedEventWithFileEntry( |
| - profile_, extension_, ASCIIToUTF16(kViewIntent), filesystem_id, |
| - registered_name); |
| + profile_, extension_, ASCIIToUTF16(web_intents::action::kView), |
| + filesystem_id, registered_name); |
| } |
| // The profile the app should be run in. |
| Profile* profile_; |
| // The extension providing the app. |
| const Extension* extension_; |
| - // The command line to be passed through to the app, or NULL. |
| - const CommandLine* command_line_; |
| - // If non-empty, this is used to expand relative paths. |
| - const FilePath current_directory_; |
| + // The path to be passed through to the app. This may be the empty path. |
| + const FilePath file_path_; |
| - DISALLOW_COPY_AND_ASSIGN(PlatformAppCommandLineLauncher); |
| + DISALLOW_COPY_AND_ASSIGN(PlatformAppPathLauncher); |
| }; |
| // Class to handle launching of platform apps with WebIntent data. |
| @@ -330,12 +335,21 @@ void LaunchPlatformApp(Profile* profile, |
| const Extension* extension, |
| const CommandLine* command_line, |
| const FilePath& current_directory) { |
| + FilePath path; |
| + if (GetAbsolutePathFromCommandLine(command_line, current_directory, &path)) |
| + LaunchPlatformAppWithPath(profile, extension, path); |
| + else |
| + LaunchPlatformAppWithNoData(profile, extension); |
|
benwells
2012/08/31 05:40:15
Nit: Use an early return here:
if (...) {
Launc
thorogood
2012/09/01 03:02:11
Done.
|
| +} |
| + |
| +void LaunchPlatformAppWithPath(Profile* profile, |
| + const Extension* extension, |
| + const FilePath& file_path) { |
| // launcher will be freed when nothing has a reference to it. The message |
| // queue will retain a reference for any outstanding task, so when the |
| // launcher has finished it will be freed. |
| - scoped_refptr<PlatformAppCommandLineLauncher> launcher = |
| - new PlatformAppCommandLineLauncher(profile, extension, command_line, |
| - current_directory); |
| + scoped_refptr<PlatformAppPathLauncher> launcher = |
| + new PlatformAppPathLauncher(profile, extension, file_path); |
| launcher->Launch(); |
| } |