| Index: chrome/browser/chromeos/extensions/file_handler_util.cc
|
| diff --git a/chrome/browser/chromeos/extensions/file_handler_util.cc b/chrome/browser/chromeos/extensions/file_handler_util.cc
|
| index d26447debe45428208213fabe20c15ac89b296b0..a576e584c2e83269ae8091480eb194ee7f5e00e0 100644
|
| --- a/chrome/browser/chromeos/extensions/file_handler_util.cc
|
| +++ b/chrome/browser/chromeos/extensions/file_handler_util.cc
|
| @@ -20,6 +20,7 @@
|
| #include "chrome/browser/extensions/extension_system.h"
|
| #include "chrome/browser/extensions/extension_tab_util.h"
|
| #include "chrome/browser/extensions/lazy_background_task_queue.h"
|
| +#include "chrome/browser/extensions/platform_app_launcher.h"
|
| #include "chrome/browser/prefs/scoped_user_pref_update.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "chrome/browser/profiles/profile_manager.h"
|
| @@ -38,6 +39,7 @@
|
| #include "webkit/fileapi/file_system_context.h"
|
| #include "webkit/fileapi/file_system_url.h"
|
| #include "webkit/fileapi/file_system_util.h"
|
| +#include "webkit/fileapi/isolated_context.h"
|
|
|
| using content::BrowserContext;
|
| using content::BrowserThread;
|
| @@ -48,11 +50,6 @@ using extensions::Extension;
|
|
|
| namespace file_handler_util {
|
|
|
| -// The prefix used to differentiate drive extensions from Chrome extensions.
|
| -const char FileTaskExecutor::kDriveTaskExtensionPrefix[] = "drive-app:";
|
| -const size_t FileTaskExecutor::kDriveTaskExtensionPrefixLength =
|
| - arraysize(FileTaskExecutor::kDriveTaskExtensionPrefix) - 1;
|
| -
|
| namespace {
|
| typedef std::set<const FileBrowserHandler*> FileBrowserHandlerSet;
|
|
|
| @@ -112,8 +109,9 @@ const FileBrowserHandler* FindFileBrowserHandler(const Extension* extension,
|
| return NULL;
|
| }
|
|
|
| -unsigned int GetAccessPermissionsForHandler(const Extension* extension,
|
| - const std::string& action_id) {
|
| +unsigned int GetAccessPermissionsForFileBrowserHandler(
|
| + const Extension* extension,
|
| + const std::string& action_id) {
|
| const FileBrowserHandler* action =
|
| FindFileBrowserHandler(extension, action_id);
|
| if (!action)
|
| @@ -127,7 +125,6 @@ unsigned int GetAccessPermissionsForHandler(const Extension* extension,
|
| return result;
|
| }
|
|
|
| -
|
| std::string EscapedUtf8ToLower(const std::string& str) {
|
| string16 utf16 = UTF8ToUTF16(
|
| net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL));
|
| @@ -245,52 +242,70 @@ int GetReadOnlyPermissions() {
|
| }
|
|
|
| std::string MakeTaskID(const std::string& extension_id,
|
| + TaskType task_type,
|
| const std::string& action_id) {
|
| - return base::StringPrintf("%s|%s", extension_id.c_str(), action_id.c_str());
|
| + DCHECK(task_type == TASK_FILE
|
| + || task_type == TASK_DRIVE
|
| + || task_type == TASK_WEBINTENT);
|
| + return base::StringPrintf("%s|%d|%s",
|
| + extension_id.c_str(),
|
| + task_type,
|
| + action_id.c_str());
|
| }
|
|
|
| -std::string MakeDriveTaskID(const std::string& app_id,
|
| - const std::string& action_id) {
|
| - return MakeTaskID(FileTaskExecutor::kDriveTaskExtensionPrefix + app_id,
|
| - action_id);
|
| -}
|
| -
|
| -bool CrackDriveTaskID(const std::string& task_id,
|
| - std::string* app_id,
|
| - std::string* action_id) {
|
| - std::string app_id_tmp;
|
| - std::string action_id_tmp;
|
| - if (!CrackTaskID(task_id, &app_id_tmp, &action_id_tmp))
|
| - return false;
|
| - if (StartsWithASCII(app_id_tmp,
|
| - FileTaskExecutor::kDriveTaskExtensionPrefix,
|
| - false)) {
|
| - // Strip off the prefix from the extension ID so we convert it to an app id.
|
| - if (app_id) {
|
| - *app_id = app_id_tmp.substr(
|
| - FileTaskExecutor::kDriveTaskExtensionPrefixLength);
|
| - }
|
| - if (action_id)
|
| - *action_id = action_id_tmp;
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| +const char kDriveTaskExtensionPrefix[] = "drive-app:";
|
| +const size_t kDriveTaskExtensionPrefixLength =
|
| + arraysize(kDriveTaskExtensionPrefix) - 1;
|
|
|
| // Breaks down task_id that is used between getFileTasks() and executeTask() on
|
| // its building blocks. task_id field the following structure:
|
| -// <extension-id>|<task-action-id>
|
| +// <extension-id>|<task-type>|<task-action-id>
|
| bool CrackTaskID(const std::string& task_id,
|
| std::string* extension_id,
|
| + TaskType* task_type,
|
| std::string* action_id) {
|
| std::vector<std::string> result;
|
| int count = Tokenize(task_id, std::string("|"), &result);
|
| - if (count != 2)
|
| +
|
| + // Parse historic task_id parameters that only contain two parts. Drive tasks
|
| + // are identified by a prefix "drive-app:" on the extension ID.
|
| + if (count == 2) {
|
| + if (StartsWithASCII(result[0], kDriveTaskExtensionPrefix, true)) {
|
| + if (task_type)
|
| + *task_type = TASK_DRIVE;
|
| +
|
| + if (extension_id)
|
| + *extension_id = result[0].substr(kDriveTaskExtensionPrefixLength);
|
| + } else {
|
| + if (task_type)
|
| + *task_type = TASK_FILE;
|
| +
|
| + if (extension_id)
|
| + *extension_id = result[0];
|
| + }
|
| +
|
| + if (action_id)
|
| + *action_id = result[1];
|
| +
|
| + return true;
|
| + }
|
| +
|
| + if (count != 3)
|
| return false;
|
| +
|
| if (extension_id)
|
| *extension_id = result[0];
|
| +
|
| + if (task_type) {
|
| + *task_type = file_handler_util::TaskType(atoi(result[1].c_str()));
|
| + DCHECK(*task_type == TASK_FILE
|
| + || *task_type == TASK_DRIVE
|
| + || *task_type == TASK_WEBINTENT);
|
| + }
|
| +
|
| if (action_id)
|
| - *action_id = result[1];
|
| + *action_id = result[2];
|
| +
|
| return true;
|
| }
|
|
|
| @@ -308,6 +323,8 @@ FileBrowserHandlerSet::iterator FindHandler(
|
| return iter;
|
| }
|
|
|
| +// Given the list of selected files, returns array of file action tasks
|
| +// that are shared between them.
|
| void FindDefaultTasks(Profile* profile,
|
| const std::vector<GURL>& files_list,
|
| const FileBrowserHandlerSet& common_tasks,
|
| @@ -336,7 +353,7 @@ void FindDefaultTasks(Profile* profile,
|
| // from common_tasks.
|
| for (FileBrowserHandlerSet::const_iterator task_iter = common_tasks.begin();
|
| task_iter != common_tasks.end(); ++task_iter) {
|
| - std::string task_id = MakeTaskID((*task_iter)->extension_id(),
|
| + std::string task_id = MakeTaskID((*task_iter)->extension_id(), TASK_FILE,
|
| (*task_iter)->id());
|
| for (std::set<std::string>::iterator default_iter = default_ids.begin();
|
| default_iter != default_ids.end(); ++default_iter) {
|
| @@ -491,7 +508,6 @@ class ExtensionTaskExecutor : public FileTaskExecutor {
|
| void InitHandlerHostFileAccessPermissions(
|
| const FileDefinitionList& file_list,
|
| const extensions::Extension* handler_extension,
|
| - const std::string& action_id,
|
| const base::Closure& callback);
|
|
|
| // Invoked upon completion of InitHandlerHostFileAccessPermissions initiated
|
| @@ -506,11 +522,7 @@ class ExtensionTaskExecutor : public FileTaskExecutor {
|
| // ChildProcessSecurityPolicy for process with id |handler_pid|.
|
| void SetupHandlerHostFileAccessPermissions(int handler_pid);
|
|
|
| - // Helper function to get the extension pointer.
|
| - const extensions::Extension* GetExtension();
|
| -
|
| const GURL source_url_;
|
| - const std::string extension_id_;
|
| const std::string action_id_;
|
| FileTaskFinishedCallback done_;
|
|
|
| @@ -518,28 +530,62 @@ class ExtensionTaskExecutor : public FileTaskExecutor {
|
| std::vector<std::pair<FilePath, int> > handler_host_permissions_;
|
| };
|
|
|
| +class WebIntentTaskExecutor : public FileTaskExecutor {
|
| + public:
|
| + // FileTaskExecutor overrides.
|
| + virtual bool ExecuteAndNotify(const std::vector<GURL>& file_urls,
|
| + const FileTaskFinishedCallback& done) OVERRIDE;
|
| +
|
| + private:
|
| + // FileTaskExecutor is the only class allowed to create one.
|
| + friend class FileTaskExecutor;
|
| +
|
| + WebIntentTaskExecutor(Profile* profile,
|
| + const GURL source_url,
|
| + const std::string& extension_id,
|
| + const std::string& action_id);
|
| + virtual ~WebIntentTaskExecutor();
|
| +
|
| + bool ExecuteForURL(const GURL& file_url);
|
| +
|
| + const GURL source_url_;
|
| + const std::string extension_id_;
|
| + const std::string action_id_;
|
| +};
|
| +
|
| // static
|
| FileTaskExecutor* FileTaskExecutor::Create(Profile* profile,
|
| const GURL source_url,
|
| const std::string& extension_id,
|
| + TaskType task_type,
|
| const std::string& action_id) {
|
| - // Check out the extension ID and see if this is a drive task,
|
| - // and instantiate drive-specific executor if so.
|
| - if (StartsWithASCII(extension_id,
|
| - FileTaskExecutor::kDriveTaskExtensionPrefix,
|
| - false)) {
|
| - return new gdata::DriveTaskExecutor(profile,
|
| - extension_id, // really app_id
|
| - action_id);
|
| - } else {
|
| - return new ExtensionTaskExecutor(profile,
|
| - source_url,
|
| - extension_id,
|
| - action_id);
|
| + switch (task_type) {
|
| + case TASK_DRIVE:
|
| + return new gdata::DriveTaskExecutor(profile,
|
| + extension_id, // really app_id
|
| + action_id);
|
| + case TASK_WEBINTENT:
|
| + return new WebIntentTaskExecutor(profile,
|
| + source_url,
|
| + extension_id,
|
| + action_id);
|
| + case TASK_FILE:
|
| + return new ExtensionTaskExecutor(profile,
|
| + source_url,
|
| + extension_id,
|
| + action_id);
|
| + default:
|
| + NOTREACHED();
|
| + return NULL;
|
| + // TODO: bigger explosion than this
|
| }
|
| }
|
|
|
| -FileTaskExecutor::FileTaskExecutor(Profile* profile) : profile_(profile) {
|
| +FileTaskExecutor::FileTaskExecutor(
|
| + Profile* profile,
|
| + const std::string& extension_id)
|
| + : profile_(profile),
|
| + extension_id_(extension_id) {
|
| }
|
|
|
| FileTaskExecutor::~FileTaskExecutor() {
|
| @@ -554,6 +600,14 @@ Browser* FileTaskExecutor::GetBrowser() const {
|
| profile_ ? profile_ : ProfileManager::GetDefaultProfileOrOffTheRecord());
|
| }
|
|
|
| +const Extension* FileTaskExecutor::GetExtension() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + ExtensionService* service = profile()->GetExtensionService();
|
| + return service ? service->GetExtensionById(extension_id_, false) :
|
| + NULL;
|
| +}
|
| +
|
| ExtensionTaskExecutor::FileDefinition::FileDefinition() : is_directory(false) {
|
| }
|
|
|
| @@ -723,9 +777,8 @@ ExtensionTaskExecutor::ExtensionTaskExecutor(
|
| const GURL source_url,
|
| const std::string& extension_id,
|
| const std::string& action_id)
|
| - : FileTaskExecutor(profile),
|
| + : FileTaskExecutor(profile, extension_id),
|
| source_url_(source_url),
|
| - extension_id_(extension_id),
|
| action_id_(action_id) {
|
| }
|
|
|
| @@ -734,12 +787,7 @@ ExtensionTaskExecutor::~ExtensionTaskExecutor() {}
|
| bool ExtensionTaskExecutor::ExecuteAndNotify(
|
| const std::vector<GURL>& file_urls,
|
| const FileTaskFinishedCallback& done) {
|
| - ExtensionService* service = profile()->GetExtensionService();
|
| - if (!service)
|
| - return false;
|
| -
|
| - scoped_refptr<const Extension> handler =
|
| - service->GetExtensionById(extension_id_, false);
|
| + scoped_refptr<const Extension> handler = GetExtension();
|
|
|
| if (!handler.get())
|
| return false;
|
| @@ -795,14 +843,6 @@ void ExtensionTaskExecutor::ExecuteDoneOnUIThread(bool success) {
|
| done_.Reset();
|
| }
|
|
|
| -const Extension* ExtensionTaskExecutor::GetExtension() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - ExtensionService* service = profile()->GetExtensionService();
|
| - return service ? service->GetExtensionById(extension_id_, false) :
|
| - NULL;
|
| -}
|
| -
|
| void ExtensionTaskExecutor::ExecuteFileActionsOnUIThread(
|
| const std::string& file_system_name,
|
| const GURL& file_system_root,
|
| @@ -819,7 +859,6 @@ void ExtensionTaskExecutor::ExecuteFileActionsOnUIThread(
|
| InitHandlerHostFileAccessPermissions(
|
| file_list,
|
| extension,
|
| - action_id_,
|
| base::Bind(
|
| &ExtensionTaskExecutor::OnInitAccessForExecuteFileActionsOnUIThread,
|
| this,
|
| @@ -855,7 +894,7 @@ void ExtensionTaskExecutor::OnInitAccessForExecuteFileActionsOnUIThread(
|
| return;
|
| }
|
| queue->AddPendingTask(
|
| - profile(), extension_id_,
|
| + profile(), extension_id(),
|
| base::Bind(&ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent,
|
| this, file_system_name, file_system_root, file_list,
|
| handler_pid));
|
| @@ -914,7 +953,7 @@ void ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent(
|
| }
|
|
|
| event_router->DispatchEventToExtension(
|
| - extension_id_, std::string("fileBrowserHandler.onExecute"),
|
| + extension_id(), std::string("fileBrowserHandler.onExecute"),
|
| event_args.Pass(), profile(), GURL());
|
| ExecuteDoneOnUIThread(true);
|
| }
|
| @@ -922,7 +961,6 @@ void ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent(
|
| void ExtensionTaskExecutor::InitHandlerHostFileAccessPermissions(
|
| const FileDefinitionList& file_list,
|
| const Extension* handler_extension,
|
| - const std::string& action_id,
|
| const base::Closure& callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| @@ -931,9 +969,9 @@ void ExtensionTaskExecutor::InitHandlerHostFileAccessPermissions(
|
| iter != file_list.end();
|
| ++iter) {
|
| // Setup permission for file's absolute file.
|
| - handler_host_permissions_.push_back(std::make_pair(
|
| - iter->absolute_path,
|
| - GetAccessPermissionsForHandler(handler_extension, action_id)));
|
| + handler_host_permissions_.push_back(std::make_pair(iter->absolute_path,
|
| + GetAccessPermissionsForFileBrowserHandler(handler_extension,
|
| + action_id_)));
|
|
|
| if (gdata::util::IsUnderDriveMountPoint(iter->absolute_path))
|
| gdata_paths->push_back(iter->virtual_path);
|
| @@ -966,4 +1004,54 @@ void ExtensionTaskExecutor::SetupHandlerHostFileAccessPermissions(
|
| handler_host_permissions_.clear();
|
| }
|
|
|
| +WebIntentTaskExecutor::WebIntentTaskExecutor(
|
| + Profile* profile,
|
| + const GURL source_url,
|
| + const std::string& extension_id,
|
| + const std::string& action_id)
|
| + : FileTaskExecutor(profile, extension_id),
|
| + source_url_(source_url),
|
| + action_id_(action_id) {
|
| +}
|
| +
|
| +WebIntentTaskExecutor::~WebIntentTaskExecutor() {}
|
| +
|
| +bool WebIntentTaskExecutor::ExecuteAndNotify(
|
| + const std::vector<GURL>& file_urls,
|
| + const FileTaskFinishedCallback& done) {
|
| + bool success = true;
|
| +
|
| + for (std::vector<GURL>::const_iterator i = file_urls.begin();
|
| + i != file_urls.end(); ++i) {
|
| + if (!ExecuteForURL(*i))
|
| + success = false;
|
| + }
|
| +
|
| + if (!done.is_null())
|
| + done.Run(success);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool WebIntentTaskExecutor::ExecuteForURL(const GURL& file_url) {
|
| + fileapi::FileSystemURL url(file_url);
|
| + if (!chromeos::CrosMountPointProvider::CanHandleURL(url))
|
| + return false;
|
| +
|
| + scoped_refptr<fileapi::FileSystemContext> file_system_context =
|
| + BrowserContext::GetFileSystemContext(profile());
|
| + fileapi::ExternalFileSystemMountPointProvider* external_provider =
|
| + file_system_context->external_provider();
|
| + if (!external_provider || !external_provider->IsAccessAllowed(url))
|
| + return false;
|
| +
|
| + // Make sure this url really being used by the right caller extension.
|
| + if (source_url_.GetOrigin() != url.origin())
|
| + return false;
|
| +
|
| + FilePath local_path = url.path();
|
| + extensions::LaunchPlatformAppWithPath(profile(), GetExtension(), local_path);
|
| + return true;
|
| +}
|
| +
|
| } // namespace file_handler_util
|
|
|