Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(533)

Unified Diff: chrome/browser/chromeos/extensions/file_handler_util.cc

Issue 13929003: chromeos: Move chrome/browser/chromeos/extensions/file_handler_util.* to a sub-directory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
deleted file mode 100644
index 298318d158bf52cec1b562ac6ce5a1e0fdb2abe3..0000000000000000000000000000000000000000
--- a/chrome/browser/chromeos/extensions/file_handler_util.cc
+++ /dev/null
@@ -1,1015 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/extensions/file_handler_util.h"
-
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/i18n/case_conversion.h"
-#include "base/json/json_writer.h"
-#include "base/string_util.h"
-#include "base/stringprintf.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/chromeos/drive/drive_file_system_util.h"
-#include "chrome/browser/chromeos/drive/drive_task_executor.h"
-#include "chrome/browser/chromeos/extensions/file_browser_handler.h"
-#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
-#include "chrome/browser/extensions/event_router.h"
-#include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/extensions/extension_service.h"
-#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"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/host_desktop.h"
-#include "chrome/common/extensions/background_info.h"
-#include "chrome/common/pref_names.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_security_policy.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/site_instance.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/web_contents.h"
-#include "net/base/escape.h"
-#include "webkit/chromeos/fileapi/cros_mount_point_provider.h"
-#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;
-using content::ChildProcessSecurityPolicy;
-using content::SiteInstance;
-using content::WebContents;
-using extensions::Extension;
-using fileapi::FileSystemURL;
-
-namespace file_handler_util {
-
-const char kTaskFile[] = "file";
-const char kTaskDrive[] = "drive";
-const char kTaskApp[] = "app";
-
-namespace {
-
-// Legacy Drive task extension prefix, used by CrackTaskID.
-const char kDriveTaskExtensionPrefix[] = "drive-app:";
-const size_t kDriveTaskExtensionPrefixLength =
- arraysize(kDriveTaskExtensionPrefix) - 1;
-
-typedef std::set<const FileBrowserHandler*> FileBrowserHandlerSet;
-
-const int kReadWriteFilePermissions = base::PLATFORM_FILE_OPEN |
- base::PLATFORM_FILE_CREATE |
- base::PLATFORM_FILE_OPEN_ALWAYS |
- base::PLATFORM_FILE_CREATE_ALWAYS |
- base::PLATFORM_FILE_OPEN_TRUNCATED |
- base::PLATFORM_FILE_READ |
- base::PLATFORM_FILE_WRITE |
- base::PLATFORM_FILE_EXCLUSIVE_READ |
- base::PLATFORM_FILE_EXCLUSIVE_WRITE |
- base::PLATFORM_FILE_ASYNC |
- base::PLATFORM_FILE_WRITE_ATTRIBUTES;
-
-const int kReadOnlyFilePermissions = base::PLATFORM_FILE_OPEN |
- base::PLATFORM_FILE_READ |
- base::PLATFORM_FILE_EXCLUSIVE_READ |
- base::PLATFORM_FILE_ASYNC;
-
-const char kFileBrowserExtensionId[] = "hhaomjibdihmijegdhdafkllkbggdgoj";
-
-// Returns process id of the process the extension is running in.
-int ExtractProcessFromExtensionId(Profile* profile,
- const std::string& extension_id) {
- GURL extension_url =
- Extension::GetBaseURLFromExtensionId(extension_id);
- ExtensionProcessManager* manager =
- extensions::ExtensionSystem::Get(profile)->process_manager();
-
- SiteInstance* site_instance = manager->GetSiteInstanceForURL(extension_url);
- if (!site_instance || !site_instance->HasProcess())
- return -1;
- content::RenderProcessHost* process = site_instance->GetProcess();
-
- return process->GetID();
-}
-
-bool IsBuiltinTask(const FileBrowserHandler* task) {
- return (task->extension_id() == kFileBrowserExtensionId ||
- task->extension_id() ==
- extension_misc::kQuickOfficeComponentExtensionId ||
- task->extension_id() == extension_misc::kQuickOfficeDevExtensionId ||
- task->extension_id() == extension_misc::kQuickOfficeExtensionId);
-}
-
-bool MatchesAllURLs(const FileBrowserHandler* handler) {
- const std::set<URLPattern>& patterns =
- handler->file_url_patterns().patterns();
- for (std::set<URLPattern>::const_iterator it = patterns.begin();
- it != patterns.end();
- ++it) {
- if (it->match_all_urls())
- return true;
- }
- return false;
-}
-
-const FileBrowserHandler* FindFileBrowserHandler(const Extension* extension,
- const std::string& action_id) {
- FileBrowserHandler::List* handler_list =
- FileBrowserHandler::GetHandlers(extension);
- for (FileBrowserHandler::List::const_iterator action_iter =
- handler_list->begin();
- action_iter != handler_list->end();
- ++action_iter) {
- if (action_iter->get()->id() == action_id)
- return action_iter->get();
- }
- return NULL;
-}
-
-unsigned int GetAccessPermissionsForFileBrowserHandler(
- const Extension* extension,
- const std::string& action_id) {
- const FileBrowserHandler* action =
- FindFileBrowserHandler(extension, action_id);
- if (!action)
- return 0;
- unsigned int result = 0;
- if (action->CanRead())
- result |= kReadOnlyFilePermissions;
- if (action->CanWrite())
- result |= kReadWriteFilePermissions;
- // TODO(tbarzic): We don't handle Create yet.
- return result;
-}
-
-std::string EscapedUtf8ToLower(const std::string& str) {
- string16 utf16 = UTF8ToUTF16(
- net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL));
- return net::EscapeUrlEncodedData(
- UTF16ToUTF8(base::i18n::ToLower(utf16)),
- false /* do not replace space with plus */);
-}
-
-bool GetFileBrowserHandlers(Profile* profile,
- const GURL& selected_file_url,
- FileBrowserHandlerSet* results) {
- ExtensionService* service =
- extensions::ExtensionSystem::Get(profile)->extension_service();
- if (!service)
- return false; // In unit-tests, we may not have an ExtensionService.
-
- // We need case-insensitive matching, and pattern in the handler is already
- // in lower case.
- const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec()));
-
- for (ExtensionSet::const_iterator iter = service->extensions()->begin();
- iter != service->extensions()->end();
- ++iter) {
- const Extension* extension = *iter;
- if (profile->IsOffTheRecord() &&
- !service->IsIncognitoEnabled(extension->id()))
- continue;
-
- FileBrowserHandler::List* handler_list =
- FileBrowserHandler::GetHandlers(extension);
- if (!handler_list)
- continue;
- for (FileBrowserHandler::List::const_iterator action_iter =
- handler_list->begin();
- action_iter != handler_list->end();
- ++action_iter) {
- const FileBrowserHandler* action = action_iter->get();
- if (!action->MatchesURL(lowercase_url))
- continue;
-
- results->insert(action_iter->get());
- }
- }
- return true;
-}
-
-} // namespace
-
-void UpdateDefaultTask(Profile* profile,
- const std::string& task_id,
- const std::set<std::string>& suffixes,
- const std::set<std::string>& mime_types) {
- if (!profile || !profile->GetPrefs())
- return;
-
- if (!mime_types.empty()) {
- DictionaryPrefUpdate mime_type_pref(profile->GetPrefs(),
- prefs::kDefaultTasksByMimeType);
- for (std::set<std::string>::const_iterator iter = mime_types.begin();
- iter != mime_types.end(); ++iter) {
- base::StringValue* value = new base::StringValue(task_id);
- mime_type_pref->SetWithoutPathExpansion(*iter, value);
- }
- }
-
- if (!suffixes.empty()) {
- DictionaryPrefUpdate mime_type_pref(profile->GetPrefs(),
- prefs::kDefaultTasksBySuffix);
- for (std::set<std::string>::const_iterator iter = suffixes.begin();
- iter != suffixes.end(); ++iter) {
- base::StringValue* value = new base::StringValue(task_id);
- // Suffixes are case insensitive.
- std::string lower_suffix = StringToLowerASCII(*iter);
- mime_type_pref->SetWithoutPathExpansion(lower_suffix, value);
- }
- }
-}
-
-std::string GetDefaultTaskIdFromPrefs(Profile* profile,
- const std::string& mime_type,
- const std::string& suffix) {
- VLOG(1) << "Looking for default for MIME type: " << mime_type
- << " and suffix: " << suffix;
- std::string task_id;
- if (!mime_type.empty()) {
- const DictionaryValue* mime_task_prefs =
- profile->GetPrefs()->GetDictionary(prefs::kDefaultTasksByMimeType);
- DCHECK(mime_task_prefs);
- LOG_IF(ERROR, !mime_task_prefs) << "Unable to open MIME type prefs";
- if (mime_task_prefs &&
- mime_task_prefs->GetStringWithoutPathExpansion(mime_type, &task_id)) {
- VLOG(1) << "Found MIME default handler: " << task_id;
- return task_id;
- }
- }
-
- const DictionaryValue* suffix_task_prefs =
- profile->GetPrefs()->GetDictionary(prefs::kDefaultTasksBySuffix);
- DCHECK(suffix_task_prefs);
- LOG_IF(ERROR, !suffix_task_prefs) << "Unable to open suffix prefs";
- std::string lower_suffix = StringToLowerASCII(suffix);
- if (suffix_task_prefs)
- suffix_task_prefs->GetStringWithoutPathExpansion(lower_suffix, &task_id);
- VLOG_IF(1, !task_id.empty()) << "Found suffix default handler: " << task_id;
- return task_id;
-}
-
-int GetReadWritePermissions() {
- return kReadWriteFilePermissions;
-}
-
-int GetReadOnlyPermissions() {
- return kReadOnlyFilePermissions;
-}
-
-std::string MakeTaskID(const std::string& extension_id,
- const std::string& task_type,
- const std::string& action_id) {
- DCHECK(task_type == kTaskFile ||
- task_type == kTaskDrive ||
- task_type == kTaskApp);
- return base::StringPrintf("%s|%s|%s",
- extension_id.c_str(),
- task_type.c_str(),
- action_id.c_str());
-}
-
-// Breaks down task_id that is used between getFileTasks() and executeTask() on
-// its building blocks. task_id field the following structure:
-// <extension-id>|<task-type>|<task-action-id>
-bool CrackTaskID(const std::string& task_id,
- std::string* extension_id,
- std::string* task_type,
- std::string* action_id) {
- std::vector<std::string> result;
- int count = Tokenize(task_id, std::string("|"), &result);
-
- // 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 = kTaskDrive;
-
- if (extension_id)
- *extension_id = result[0].substr(kDriveTaskExtensionPrefixLength);
- } else {
- if (task_type)
- *task_type = kTaskFile;
-
- 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 = result[1];
- DCHECK(*task_type == kTaskFile ||
- *task_type == kTaskDrive ||
- *task_type == kTaskApp);
- }
-
- if (action_id)
- *action_id = result[2];
-
- return true;
-}
-
-// Find a specific handler in the handler list.
-FileBrowserHandlerSet::iterator FindHandler(
- FileBrowserHandlerSet* handler_set,
- const std::string& extension_id,
- const std::string& id) {
- FileBrowserHandlerSet::iterator iter = handler_set->begin();
- while (iter != handler_set->end() &&
- !((*iter)->extension_id() == extension_id &&
- (*iter)->id() == id)) {
- iter++;
- }
- 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<base::FilePath>& files_list,
- const FileBrowserHandlerSet& common_tasks,
- FileBrowserHandlerSet* default_tasks) {
- DCHECK(default_tasks);
- default_tasks->clear();
-
- std::set<std::string> default_ids;
- for (std::vector<base::FilePath>::const_iterator it = files_list.begin();
- it != files_list.end(); ++it) {
- std::string task_id = file_handler_util::GetDefaultTaskIdFromPrefs(
- profile, "", it->Extension());
- if (!task_id.empty())
- default_ids.insert(task_id);
- }
-
- const FileBrowserHandler* builtin_task = NULL;
- // Convert the default task IDs collected above to one of the handler pointers
- // 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(), kTaskFile,
- (*task_iter)->id());
- std::set<std::string>::iterator default_iter = default_ids.find(task_id);
- if (default_iter != default_ids.end()) {
- default_tasks->insert(*task_iter);
- continue;
- }
-
- // If it's a built in task, remember it. If there are no default tasks among
- // common tasks, builtin task will be used as a fallback.
- // Note that builtin tasks are not overlapping, so there can be at most one
- // builtin tasks for each set of files.
- if (IsBuiltinTask(*task_iter))
- builtin_task = *task_iter;
- }
-
- // If there are no default tasks found, use builtin task (if found) as a
- // default.
- if (builtin_task && default_tasks->empty())
- default_tasks->insert(builtin_task);
-}
-
-// Given the list of selected files, returns array of context menu tasks
-// that are shared
-bool FindCommonTasks(Profile* profile,
- const std::vector<GURL>& files_list,
- FileBrowserHandlerSet* common_tasks) {
- DCHECK(common_tasks);
- common_tasks->clear();
-
- FileBrowserHandlerSet common_task_set;
- std::set<std::string> default_task_ids;
- for (std::vector<GURL>::const_iterator it = files_list.begin();
- it != files_list.end(); ++it) {
- FileBrowserHandlerSet file_actions;
- if (!GetFileBrowserHandlers(profile, *it, &file_actions))
- return false;
- // If there is nothing to do for one file, the intersection of tasks for all
- // files will be empty at the end, and so will the default tasks.
- if (file_actions.empty())
- return true;
-
- // For the very first file, just copy all the elements.
- if (it == files_list.begin()) {
- common_task_set = file_actions;
- } else {
- // For all additional files, find intersection between the accumulated and
- // file specific set.
- FileBrowserHandlerSet intersection;
- std::set_intersection(common_task_set.begin(), common_task_set.end(),
- file_actions.begin(), file_actions.end(),
- std::inserter(intersection,
- intersection.begin()));
- common_task_set = intersection;
- if (common_task_set.empty())
- return true;
- }
- }
-
- FileBrowserHandlerSet::iterator watch_iter = FindHandler(
- &common_task_set, kFileBrowserDomain, kFileBrowserWatchTaskId);
- FileBrowserHandlerSet::iterator gallery_iter = FindHandler(
- &common_task_set, kFileBrowserDomain, kFileBrowserGalleryTaskId);
- if (watch_iter != common_task_set.end() &&
- gallery_iter != common_task_set.end()) {
- // Both "watch" and "gallery" actions are applicable which means that the
- // selection is all videos. Showing them both is confusing, so we only keep
- // the one that makes more sense ("watch" for single selection, "gallery"
- // for multiple selection).
- if (files_list.size() == 1)
- common_task_set.erase(gallery_iter);
- else
- common_task_set.erase(watch_iter);
- }
-
- common_tasks->swap(common_task_set);
- return true;
-}
-
-bool GetTaskForURLAndPath(Profile* profile,
- const GURL& url,
- const base::FilePath& file_path,
- const FileBrowserHandler** handler) {
- std::vector<GURL> file_urls;
- file_urls.push_back(url);
-
- FileBrowserHandlerSet default_tasks;
- FileBrowserHandlerSet common_tasks;
- if (!FindCommonTasks(profile, file_urls, &common_tasks))
- return false;
-
- if (common_tasks.empty())
- return false;
-
- std::vector<base::FilePath> file_paths;
- file_paths.push_back(file_path);
-
- FindDefaultTasks(profile, file_paths, common_tasks, &default_tasks);
-
- // If there's none, or more than one, then we don't have a canonical default.
- if (!default_tasks.empty()) {
- // There should not be multiple default tasks for a single URL.
- DCHECK_EQ(1u, default_tasks.size());
-
- *handler = *default_tasks.begin();
- return true;
- }
-
- // If there are no default tasks, use first task in the list (file manager
- // does the same in this situation).
- // TODO(tbarzic): This is so not optimal behaviour.
- *handler = *common_tasks.begin();
- return true;
-}
-
-class ExtensionTaskExecutor : public FileTaskExecutor {
- public:
- // FileTaskExecutor overrides.
- virtual bool ExecuteAndNotify(const std::vector<FileSystemURL>& file_urls,
- const FileTaskFinishedCallback& done) OVERRIDE;
-
- private:
- // FileTaskExecutor is the only class allowed to create one.
- friend class FileTaskExecutor;
-
- ExtensionTaskExecutor(Profile* profile,
- const GURL& source_url,
- const std::string& file_browser_id,
- int32 tab_id,
- const std::string& extension_id,
- const std::string& action_id);
- virtual ~ExtensionTaskExecutor();
-
- struct FileDefinition {
- FileDefinition();
- ~FileDefinition();
-
- base::FilePath virtual_path;
- base::FilePath absolute_path;
- bool is_directory;
- };
-
- typedef std::vector<FileDefinition> FileDefinitionList;
- class ExecuteTasksFileSystemCallbackDispatcher;
- void RequestFileEntryOnFileThread(
- scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
- const GURL& handler_base_url,
- const scoped_refptr<const extensions::Extension>& handler,
- int handler_pid,
- const std::vector<FileSystemURL>& file_urls);
-
- void ExecuteDoneOnUIThread(bool success);
- void ExecuteFileActionsOnUIThread(const std::string& file_system_name,
- const GURL& file_system_root,
- const FileDefinitionList& file_list,
- int handler_pid);
- void SetupPermissionsAndDispatchEvent(const std::string& file_system_name,
- const GURL& file_system_root,
- const FileDefinitionList& file_list,
- int handler_pid_in,
- extensions::ExtensionHost* host);
-
- // Registers file permissions from |handler_host_permissions_| with
- // ChildProcessSecurityPolicy for process with id |handler_pid|.
- void SetupHandlerHostFileAccessPermissions(
- const FileDefinitionList& file_list,
- const Extension* extension,
- int handler_pid);
-
- int32 tab_id_;
- const std::string action_id_;
- FileTaskFinishedCallback done_;
-};
-
-class AppTaskExecutor : public FileTaskExecutor {
- public:
- // FileTaskExecutor overrides.
- virtual bool ExecuteAndNotify(const std::vector<FileSystemURL>& file_urls,
- const FileTaskFinishedCallback& done) OVERRIDE;
-
- private:
- // FileTaskExecutor is the only class allowed to create one.
- friend class FileTaskExecutor;
-
- AppTaskExecutor(Profile* profile,
- const GURL& source_url,
- const std::string& file_browser_id,
- const std::string& extension_id,
- const std::string& action_id);
- virtual ~AppTaskExecutor();
-
- const std::string extension_id_;
- const std::string action_id_;
-};
-
-// static
-FileTaskExecutor* FileTaskExecutor::Create(Profile* profile,
- const GURL& source_url,
- const std::string& file_browser_id,
- int32 tab_id,
- const std::string& extension_id,
- const std::string& task_type,
- const std::string& action_id) {
- if (task_type == kTaskFile)
- return new ExtensionTaskExecutor(profile,
- source_url,
- file_browser_id,
- tab_id,
- extension_id,
- action_id);
-
- if (task_type == kTaskDrive)
- return new drive::DriveTaskExecutor(profile,
- extension_id, // really app_id
- action_id);
-
- if (task_type == kTaskApp)
- return new AppTaskExecutor(profile,
- source_url,
- file_browser_id,
- extension_id,
- action_id);
-
- NOTREACHED();
- return NULL;
-}
-
-FileTaskExecutor::FileTaskExecutor(Profile* profile,
- const GURL& source_url,
- const std::string& file_browser_id,
- const std::string& extension_id)
- : profile_(profile),
- source_url_(source_url),
- file_browser_id_(file_browser_id),
- extension_id_(extension_id) {
-}
-
-FileTaskExecutor::~FileTaskExecutor() {
-}
-
-bool FileTaskExecutor::Execute(const std::vector<FileSystemURL>& file_urls) {
- return ExecuteAndNotify(file_urls, FileTaskFinishedCallback());
-}
-
-bool FileTaskExecutor::FileBrowserHasAccessPermissionForFiles(
- const std::vector<FileSystemURL>& files) {
- // Check if the file browser extension has permissions for the files in its
- // file system context.
- GURL site = extensions::ExtensionSystem::Get(profile())->extension_service()->
- GetSiteForExtensionId(file_browser_id_);
- fileapi::ExternalFileSystemMountPointProvider* external_provider =
- BrowserContext::GetStoragePartitionForSite(profile(), site)->
- GetFileSystemContext()->external_provider();
-
- if (!external_provider)
- return false;
-
- for (size_t i = 0; i < files.size(); ++i) {
- // Make sure this url really being used by the right caller extension.
- if (source_url_.GetOrigin() != files[i].origin())
- return false;
-
- if (!chromeos::CrosMountPointProvider::CanHandleURL(files[i]) ||
- !external_provider->IsAccessAllowed(files[i])) {
- return false;
- }
- }
-
- return true;
-}
-
-// TODO(kaznacheev): Remove this method and inline its implementation at the
-// only place where it is used (DriveTaskExecutor::OnAppAuthorized)
-Browser* FileTaskExecutor::GetBrowser() const {
- return chrome::FindOrCreateTabbedBrowser(
- profile_ ? profile_ : ProfileManager::GetDefaultProfileOrOffTheRecord(),
- chrome::HOST_DESKTOP_TYPE_ASH);
-}
-
-const Extension* FileTaskExecutor::GetExtension() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- ExtensionService* service =
- extensions::ExtensionSystem::Get(profile())->extension_service();
- return service ? service->GetExtensionById(extension_id_, false) :
- NULL;
-}
-
-ExtensionTaskExecutor::FileDefinition::FileDefinition() : is_directory(false) {
-}
-
-ExtensionTaskExecutor::FileDefinition::~FileDefinition() {
-}
-
-class ExtensionTaskExecutor::ExecuteTasksFileSystemCallbackDispatcher {
- public:
- static fileapi::FileSystemContext::OpenFileSystemCallback CreateCallback(
- ExtensionTaskExecutor* executor,
- scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
- scoped_refptr<const Extension> handler_extension,
- int handler_pid,
- const std::string& action_id,
- const std::vector<FileSystemURL>& file_urls) {
- return base::Bind(
- &ExecuteTasksFileSystemCallbackDispatcher::DidOpenFileSystem,
- base::Owned(new ExecuteTasksFileSystemCallbackDispatcher(
- executor, file_system_context_handler, handler_extension,
- handler_pid, action_id, file_urls)));
- }
-
- void DidOpenFileSystem(base::PlatformFileError result,
- const std::string& file_system_name,
- const GURL& file_system_root) {
- if (result != base::PLATFORM_FILE_OK) {
- DidFail(result);
- return;
- }
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- ExtensionTaskExecutor::FileDefinitionList file_list;
- for (std::vector<FileSystemURL>::iterator iter = urls_.begin();
- iter != urls_.end();
- ++iter) {
- // Set up file permission access.
- ExtensionTaskExecutor::FileDefinition file;
- if (!SetupFileAccessPermissions(*iter, &file))
- continue;
- file_list.push_back(file);
- }
- if (file_list.empty()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &ExtensionTaskExecutor::ExecuteDoneOnUIThread,
- executor_,
- false));
- return;
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &ExtensionTaskExecutor::ExecuteFileActionsOnUIThread,
- executor_,
- file_system_name,
- file_system_root,
- file_list,
- handler_pid_));
- }
-
- void DidFail(base::PlatformFileError error_code) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &ExtensionTaskExecutor::ExecuteDoneOnUIThread,
- executor_,
- false));
- }
-
- private:
- ExecuteTasksFileSystemCallbackDispatcher(
- ExtensionTaskExecutor* executor,
- scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
- const scoped_refptr<const Extension>& handler_extension,
- int handler_pid,
- const std::string& action_id,
- const std::vector<FileSystemURL>& file_urls)
- : executor_(executor),
- file_system_context_handler_(file_system_context_handler),
- handler_extension_(handler_extension),
- handler_pid_(handler_pid),
- action_id_(action_id),
- urls_(file_urls) {
- DCHECK(executor_);
- }
-
- // Checks legitimacy of file url and grants file RO access permissions from
- // handler (target) extension and its renderer process.
- bool SetupFileAccessPermissions(const FileSystemURL& url,
- FileDefinition* file) {
- if (!handler_extension_.get())
- return false;
-
- if (handler_pid_ == 0)
- return false;
-
- fileapi::ExternalFileSystemMountPointProvider* external_provider_handler =
- file_system_context_handler_->external_provider();
-
- // Check if this file system entry exists first.
- base::PlatformFileInfo file_info;
-
- base::FilePath local_path = url.path();
- base::FilePath virtual_path = url.virtual_path();
-
- bool is_drive_file = url.type() == fileapi::kFileSystemTypeDrive;
- DCHECK(!is_drive_file || drive::util::IsUnderDriveMountPoint(local_path));
-
- // If the file is under gdata mount point, there is no actual file to be
- // found on the url.path().
- if (!is_drive_file) {
- if (!file_util::PathExists(local_path) ||
- file_util::IsLink(local_path) ||
- !file_util::GetFileInfo(local_path, &file_info)) {
- return false;
- }
- }
-
- // Grant access to this particular file to target extension. This will
- // ensure that the target extension can access only this FS entry and
- // prevent from traversing FS hierarchy upward.
- external_provider_handler->GrantFileAccessToExtension(
- handler_extension_->id(), virtual_path);
-
- // Output values.
- file->virtual_path = virtual_path;
- file->is_directory = file_info.is_directory;
- file->absolute_path = local_path;
- return true;
- }
-
- ExtensionTaskExecutor* executor_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_handler_;
- scoped_refptr<const Extension> handler_extension_;
- int handler_pid_;
- std::string action_id_;
- std::vector<FileSystemURL> urls_;
- DISALLOW_COPY_AND_ASSIGN(ExecuteTasksFileSystemCallbackDispatcher);
-};
-
-ExtensionTaskExecutor::ExtensionTaskExecutor(
- Profile* profile,
- const GURL& source_url,
- const std::string& file_browser_id,
- int tab_id,
- const std::string& extension_id,
- const std::string& action_id)
- : FileTaskExecutor(profile, source_url, file_browser_id, extension_id),
- tab_id_(tab_id),
- action_id_(action_id) {
-}
-
-ExtensionTaskExecutor::~ExtensionTaskExecutor() {}
-
-bool ExtensionTaskExecutor::ExecuteAndNotify(
- const std::vector<FileSystemURL>& file_urls,
- const FileTaskFinishedCallback& done) {
- if (!FileBrowserHasAccessPermissionForFiles(file_urls))
- return false;
-
- scoped_refptr<const Extension> handler = GetExtension();
- if (!handler.get())
- return false;
-
- int handler_pid = ExtractProcessFromExtensionId(profile(), handler->id());
- if (handler_pid <= 0) {
- if (!extensions::BackgroundInfo::HasLazyBackgroundPage(handler))
- return false;
- }
-
- done_ = done;
-
- // Get file system context for the extension to which onExecute event will be
- // send. The file access permissions will be granted to the extension in the
- // file system context for the files in |file_urls|.
- GURL site = extensions::ExtensionSystem::Get(profile())->extension_service()->
- GetSiteForExtensionId(handler->id());
- scoped_refptr<fileapi::FileSystemContext> file_system_context_handler =
- BrowserContext::GetStoragePartitionForSite(profile(), site)->
- GetFileSystemContext();
-
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(
- &ExtensionTaskExecutor::RequestFileEntryOnFileThread,
- this,
- file_system_context_handler,
- Extension::GetBaseURLFromExtensionId(handler->id()),
- handler,
- handler_pid,
- file_urls));
- return true;
-}
-
-void ExtensionTaskExecutor::RequestFileEntryOnFileThread(
- scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
- const GURL& handler_base_url,
- const scoped_refptr<const Extension>& handler,
- int handler_pid,
- const std::vector<FileSystemURL>& file_urls) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- GURL origin_url = handler_base_url.GetOrigin();
- file_system_context_handler->OpenFileSystem(
- origin_url, fileapi::kFileSystemTypeExternal, false, // create
- ExecuteTasksFileSystemCallbackDispatcher::CreateCallback(
- this,
- file_system_context_handler,
- handler,
- handler_pid,
- action_id_,
- file_urls));
-}
-
-void ExtensionTaskExecutor::ExecuteDoneOnUIThread(bool success) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!done_.is_null())
- done_.Run(success);
- done_.Reset();
-}
-
-void ExtensionTaskExecutor::ExecuteFileActionsOnUIThread(
- const std::string& file_system_name,
- const GURL& file_system_root,
- const FileDefinitionList& file_list,
- int handler_pid) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- const Extension* extension = GetExtension();
- if (!extension) {
- ExecuteDoneOnUIThread(false);
- return;
- }
-
- if (handler_pid > 0) {
- SetupPermissionsAndDispatchEvent(file_system_name, file_system_root,
- file_list, handler_pid, NULL);
- } else {
- // We have to wake the handler background page before we proceed.
- extensions::LazyBackgroundTaskQueue* queue =
- extensions::ExtensionSystem::Get(profile())->
- lazy_background_task_queue();
- if (!queue->ShouldEnqueueTask(profile(), extension)) {
- ExecuteDoneOnUIThread(false);
- return;
- }
- queue->AddPendingTask(
- profile(), extension_id(),
- base::Bind(&ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent,
- this, file_system_name, file_system_root, file_list,
- handler_pid));
- }
-}
-
-void ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent(
- const std::string& file_system_name,
- const GURL& file_system_root,
- const FileDefinitionList& file_list,
- int handler_pid_in,
- extensions::ExtensionHost* host) {
- int handler_pid = host ? host->render_process_host()->GetID() :
- handler_pid_in;
-
- if (handler_pid <= 0) {
- ExecuteDoneOnUIThread(false);
- return;
- }
-
- extensions::EventRouter* event_router =
- extensions::ExtensionSystem::Get(profile())->event_router();
- if (!event_router) {
- ExecuteDoneOnUIThread(false);
- return;
- }
-
- const Extension* extension = GetExtension();
- if (!extension) {
- ExecuteDoneOnUIThread(false);
- return;
- }
-
- SetupHandlerHostFileAccessPermissions(file_list, extension, handler_pid);
-
- scoped_ptr<ListValue> event_args(new ListValue());
- event_args->Append(new base::StringValue(action_id_));
- DictionaryValue* details = new DictionaryValue();
- event_args->Append(details);
- // Get file definitions. These will be replaced with Entry instances by
- // chromeHidden.Event.dispatchEvent() method from event_binding.js.
- ListValue* files_urls = new ListValue();
- details->Set("entries", files_urls);
- for (FileDefinitionList::const_iterator iter = file_list.begin();
- iter != file_list.end();
- ++iter) {
- DictionaryValue* file_def = new DictionaryValue();
- files_urls->Append(file_def);
- file_def->SetString("fileSystemName", file_system_name);
- file_def->SetString("fileSystemRoot", file_system_root.spec());
- base::FilePath root(FILE_PATH_LITERAL("/"));
- base::FilePath full_path = root.Append(iter->virtual_path);
- file_def->SetString("fileFullPath", full_path.value());
- file_def->SetBoolean("fileIsDirectory", iter->is_directory);
- }
-
- details->SetInteger("tab_id", tab_id_);
-
- scoped_ptr<extensions::Event> event(new extensions::Event(
- "fileBrowserHandler.onExecute", event_args.Pass()));
- event->restrict_to_profile = profile();
- event_router->DispatchEventToExtension(extension_id(), event.Pass());
-
- ExecuteDoneOnUIThread(true);
-}
-
-void ExtensionTaskExecutor::SetupHandlerHostFileAccessPermissions(
- const FileDefinitionList& file_list,
- const Extension* extension,
- int handler_pid) {
- for (FileDefinitionList::const_iterator iter = file_list.begin();
- iter != file_list.end();
- ++iter) {
- content::ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile(
- handler_pid,
- iter->absolute_path,
- GetAccessPermissionsForFileBrowserHandler(extension, action_id_));
- }
-}
-
-AppTaskExecutor::AppTaskExecutor(
- Profile* profile,
- const GURL& source_url,
- const std::string& file_browser_id,
- const std::string& extension_id,
- const std::string& action_id)
- : FileTaskExecutor(profile, source_url, file_browser_id, extension_id),
- action_id_(action_id) {
-}
-
-AppTaskExecutor::~AppTaskExecutor() {}
-
-bool AppTaskExecutor::ExecuteAndNotify(
- const std::vector<FileSystemURL>& file_urls,
- const FileTaskFinishedCallback& done) {
- if (!FileBrowserHasAccessPermissionForFiles(file_urls))
- return false;
-
- for (size_t i = 0; i != file_urls.size(); ++i) {
- extensions::LaunchPlatformAppWithFileHandler(profile(), GetExtension(),
- action_id_, file_urls[i].path());
- }
-
- if (!done.is_null())
- done.Run(true);
- return true;
-}
-
-} // namespace file_handler_util

Powered by Google App Engine
This is Rietveld 408576698