| Index: extensions/browser/api/file_handlers/app_file_handler_util.cc
|
| diff --git a/extensions/browser/api/file_handlers/app_file_handler_util.cc b/extensions/browser/api/file_handlers/app_file_handler_util.cc
|
| deleted file mode 100644
|
| index 1e7daae4eb0da923f2ae5a6d65e4d22e772c656c..0000000000000000000000000000000000000000
|
| --- a/extensions/browser/api/file_handlers/app_file_handler_util.cc
|
| +++ /dev/null
|
| @@ -1,359 +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 "extensions/browser/api/file_handlers/app_file_handler_util.h"
|
| -
|
| -#include "base/files/file.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/files/file_util.h"
|
| -#include "build/build_config.h"
|
| -#include "content/public/browser/browser_context.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "content/public/browser/child_process_security_policy.h"
|
| -#include "extensions/browser/api/extensions_api_client.h"
|
| -#include "extensions/browser/entry_info.h"
|
| -#include "extensions/browser/extension_prefs.h"
|
| -#include "extensions/browser/granted_file_entry.h"
|
| -#include "extensions/common/permissions/permissions_data.h"
|
| -#include "net/base/mime_util.h"
|
| -#include "storage/browser/fileapi/isolated_context.h"
|
| -#include "storage/common/fileapi/file_system_mount_option.h"
|
| -#include "storage/common/fileapi/file_system_types.h"
|
| -
|
| -#if defined(OS_CHROMEOS)
|
| -#include "extensions/browser/api/file_handlers/non_native_file_system_delegate.h"
|
| -#endif
|
| -
|
| -namespace extensions {
|
| -
|
| -namespace app_file_handler_util {
|
| -
|
| -const char kInvalidParameters[] = "Invalid parameters";
|
| -const char kSecurityError[] = "Security error";
|
| -
|
| -namespace {
|
| -
|
| -bool FileHandlerCanHandleFileWithExtension(const FileHandlerInfo& handler,
|
| - const base::FilePath& path) {
|
| - for (std::set<std::string>::const_iterator extension =
|
| - handler.extensions.begin();
|
| - extension != handler.extensions.end(); ++extension) {
|
| - if (*extension == "*")
|
| - return true;
|
| -
|
| - // Accept files whose extension or combined extension (e.g. ".tar.gz")
|
| - // match the supported extensions of file handler.
|
| - base::FilePath::StringType handler_extention(
|
| - base::FilePath::kExtensionSeparator +
|
| - base::FilePath::FromUTF8Unsafe(*extension).value());
|
| - if (base::FilePath::CompareEqualIgnoreCase(handler_extention,
|
| - path.Extension()) ||
|
| - base::FilePath::CompareEqualIgnoreCase(handler_extention,
|
| - path.FinalExtension())) {
|
| - return true;
|
| - }
|
| -
|
| - // Also accept files with no extension for handlers that support an
|
| - // empty extension, i.e. both "foo" and "foo." match.
|
| - if (extension->empty() &&
|
| - path.MatchesExtension(base::FilePath::StringType())) {
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool FileHandlerCanHandleFileWithMimeType(const FileHandlerInfo& handler,
|
| - const std::string& mime_type) {
|
| - for (std::set<std::string>::const_iterator type = handler.types.begin();
|
| - type != handler.types.end(); ++type) {
|
| - if (net::MatchesMimeType(*type, mime_type))
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool PrepareNativeLocalFileForWritableApp(const base::FilePath& path,
|
| - bool is_directory) {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
|
| -
|
| - // Don't allow links.
|
| - if (base::PathExists(path) && base::IsLink(path))
|
| - return false;
|
| -
|
| - if (is_directory)
|
| - return base::DirectoryExists(path);
|
| -
|
| - // Create the file if it doesn't already exist.
|
| - int creation_flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ;
|
| - base::File file(path, creation_flags);
|
| -
|
| - return file.IsValid();
|
| -}
|
| -
|
| -// Checks whether a list of paths are all OK for writing and calls a provided
|
| -// on_success or on_failure callback when done. A path is OK for writing if it
|
| -// is not a symlink, is not in a blacklisted path and can be opened for writing.
|
| -// Creates files if they do not exist, but fails for non-existent directory
|
| -// paths. On Chrome OS, also fails for non-local files that don't already exist.
|
| -class WritableFileChecker
|
| - : public base::RefCountedThreadSafe<WritableFileChecker> {
|
| - public:
|
| - WritableFileChecker(
|
| - const std::vector<base::FilePath>& paths,
|
| - content::BrowserContext* context,
|
| - const std::set<base::FilePath>& directory_paths,
|
| - const base::Closure& on_success,
|
| - const base::Callback<void(const base::FilePath&)>& on_failure);
|
| -
|
| - void Check();
|
| -
|
| - private:
|
| - friend class base::RefCountedThreadSafe<WritableFileChecker>;
|
| - virtual ~WritableFileChecker();
|
| -
|
| - // Called when a work item is completed. If all work items are done, this
|
| - // calls the success or failure callback.
|
| - void TaskDone();
|
| -
|
| - // Reports an error in completing a work item. This may be called more than
|
| - // once, but only the last message will be retained.
|
| - void Error(const base::FilePath& error_path);
|
| -
|
| - void CheckLocalWritableFiles();
|
| -
|
| - // Called when processing a file is completed with either a success or an
|
| - // error.
|
| - void OnPrepareFileDone(const base::FilePath& path, bool success);
|
| -
|
| - const std::vector<base::FilePath> paths_;
|
| - content::BrowserContext* context_;
|
| - const std::set<base::FilePath> directory_paths_;
|
| - size_t outstanding_tasks_;
|
| - base::FilePath error_path_;
|
| - base::Closure on_success_;
|
| - base::Callback<void(const base::FilePath&)> on_failure_;
|
| -};
|
| -
|
| -WritableFileChecker::WritableFileChecker(
|
| - const std::vector<base::FilePath>& paths,
|
| - content::BrowserContext* context,
|
| - const std::set<base::FilePath>& directory_paths,
|
| - const base::Closure& on_success,
|
| - const base::Callback<void(const base::FilePath&)>& on_failure)
|
| - : paths_(paths),
|
| - context_(context),
|
| - directory_paths_(directory_paths),
|
| - outstanding_tasks_(1),
|
| - on_success_(on_success),
|
| - on_failure_(on_failure) {}
|
| -
|
| -void WritableFileChecker::Check() {
|
| - outstanding_tasks_ = paths_.size();
|
| - for (const auto& path : paths_) {
|
| - bool is_directory = directory_paths_.find(path) != directory_paths_.end();
|
| -#if defined(OS_CHROMEOS)
|
| - NonNativeFileSystemDelegate* delegate =
|
| - ExtensionsAPIClient::Get()->GetNonNativeFileSystemDelegate();
|
| - if (delegate && delegate->IsUnderNonNativeLocalPath(context_, path)) {
|
| - if (is_directory) {
|
| - delegate->IsNonNativeLocalPathDirectory(
|
| - context_, path,
|
| - base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path));
|
| - } else {
|
| - delegate->PrepareNonNativeLocalFileForWritableApp(
|
| - context_, path,
|
| - base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path));
|
| - }
|
| - continue;
|
| - }
|
| -#endif
|
| - content::BrowserThread::PostTaskAndReplyWithResult(
|
| - content::BrowserThread::FILE, FROM_HERE,
|
| - base::Bind(&PrepareNativeLocalFileForWritableApp, path, is_directory),
|
| - base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path));
|
| - }
|
| -}
|
| -
|
| -WritableFileChecker::~WritableFileChecker() {}
|
| -
|
| -void WritableFileChecker::TaskDone() {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| - if (--outstanding_tasks_ == 0) {
|
| - if (error_path_.empty())
|
| - on_success_.Run();
|
| - else
|
| - on_failure_.Run(error_path_);
|
| - }
|
| -}
|
| -
|
| -// Reports an error in completing a work item. This may be called more than
|
| -// once, but only the last message will be retained.
|
| -void WritableFileChecker::Error(const base::FilePath& error_path) {
|
| - DCHECK(!error_path.empty());
|
| - error_path_ = error_path;
|
| - TaskDone();
|
| -}
|
| -
|
| -void WritableFileChecker::OnPrepareFileDone(const base::FilePath& path,
|
| - bool success) {
|
| - if (success)
|
| - TaskDone();
|
| - else
|
| - Error(path);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -const FileHandlerInfo* FileHandlerForId(const Extension& app,
|
| - const std::string& handler_id) {
|
| - const FileHandlersInfo* file_handlers = FileHandlers::GetFileHandlers(&app);
|
| - if (!file_handlers)
|
| - return NULL;
|
| -
|
| - for (FileHandlersInfo::const_iterator i = file_handlers->begin();
|
| - i != file_handlers->end(); i++) {
|
| - if (i->id == handler_id)
|
| - return &*i;
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -std::vector<const FileHandlerInfo*> FindFileHandlersForEntries(
|
| - const Extension& app,
|
| - const std::vector<EntryInfo> entries) {
|
| - std::vector<const FileHandlerInfo*> handlers;
|
| - if (entries.empty())
|
| - return handlers;
|
| -
|
| - // Look for file handlers which can handle all the MIME types specified.
|
| - const FileHandlersInfo* file_handlers = FileHandlers::GetFileHandlers(&app);
|
| - if (!file_handlers)
|
| - return handlers;
|
| -
|
| - for (FileHandlersInfo::const_iterator data = file_handlers->begin();
|
| - data != file_handlers->end(); ++data) {
|
| - bool handles_all_types = true;
|
| - for (std::vector<EntryInfo>::const_iterator it = entries.begin();
|
| - it != entries.end(); ++it) {
|
| - if (!FileHandlerCanHandleEntry(*data, *it)) {
|
| - handles_all_types = false;
|
| - break;
|
| - }
|
| - }
|
| - if (handles_all_types)
|
| - handlers.push_back(&*data);
|
| - }
|
| - return handlers;
|
| -}
|
| -
|
| -bool FileHandlerCanHandleEntry(const FileHandlerInfo& handler,
|
| - const EntryInfo& entry) {
|
| - if (entry.is_directory)
|
| - return handler.include_directories;
|
| -
|
| - return FileHandlerCanHandleFileWithMimeType(handler, entry.mime_type) ||
|
| - FileHandlerCanHandleFileWithExtension(handler, entry.path);
|
| -}
|
| -
|
| -GrantedFileEntry CreateFileEntry(content::BrowserContext* context,
|
| - const Extension* extension,
|
| - int renderer_id,
|
| - const base::FilePath& path,
|
| - bool is_directory) {
|
| - GrantedFileEntry result;
|
| - storage::IsolatedContext* isolated_context =
|
| - storage::IsolatedContext::GetInstance();
|
| - DCHECK(isolated_context);
|
| -
|
| - result.filesystem_id = isolated_context->RegisterFileSystemForPath(
|
| - storage::kFileSystemTypeNativeForPlatformApp, std::string(), path,
|
| - &result.registered_name);
|
| -
|
| - content::ChildProcessSecurityPolicy* policy =
|
| - content::ChildProcessSecurityPolicy::GetInstance();
|
| - policy->GrantReadFileSystem(renderer_id, result.filesystem_id);
|
| - if (HasFileSystemWritePermission(extension)) {
|
| - if (is_directory) {
|
| - policy->GrantCreateReadWriteFileSystem(renderer_id, result.filesystem_id);
|
| - } else {
|
| - policy->GrantWriteFileSystem(renderer_id, result.filesystem_id);
|
| - policy->GrantDeleteFromFileSystem(renderer_id, result.filesystem_id);
|
| - }
|
| - }
|
| -
|
| - result.id = result.filesystem_id + ":" + result.registered_name;
|
| - return result;
|
| -}
|
| -
|
| -void PrepareFilesForWritableApp(
|
| - const std::vector<base::FilePath>& paths,
|
| - content::BrowserContext* context,
|
| - const std::set<base::FilePath>& directory_paths,
|
| - const base::Closure& on_success,
|
| - const base::Callback<void(const base::FilePath&)>& on_failure) {
|
| - scoped_refptr<WritableFileChecker> checker(new WritableFileChecker(
|
| - paths, context, directory_paths, on_success, on_failure));
|
| - checker->Check();
|
| -}
|
| -
|
| -bool HasFileSystemWritePermission(const Extension* extension) {
|
| - return extension->permissions_data()->HasAPIPermission(
|
| - APIPermission::kFileSystemWrite);
|
| -}
|
| -
|
| -bool ValidateFileEntryAndGetPath(const std::string& filesystem_name,
|
| - const std::string& filesystem_path,
|
| - int render_process_id,
|
| - base::FilePath* file_path,
|
| - std::string* error) {
|
| - if (filesystem_path.empty()) {
|
| - *error = kInvalidParameters;
|
| - return false;
|
| - }
|
| -
|
| - std::string filesystem_id;
|
| - if (!storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) {
|
| - *error = kInvalidParameters;
|
| - return false;
|
| - }
|
| -
|
| - // Only return the display path if the process has read access to the
|
| - // filesystem.
|
| - content::ChildProcessSecurityPolicy* policy =
|
| - content::ChildProcessSecurityPolicy::GetInstance();
|
| - if (!policy->CanReadFileSystem(render_process_id, filesystem_id)) {
|
| - *error = kSecurityError;
|
| - return false;
|
| - }
|
| -
|
| - storage::IsolatedContext* context = storage::IsolatedContext::GetInstance();
|
| - base::FilePath relative_path =
|
| - base::FilePath::FromUTF8Unsafe(filesystem_path);
|
| - base::FilePath virtual_path =
|
| - context->CreateVirtualRootPath(filesystem_id).Append(relative_path);
|
| - storage::FileSystemType type;
|
| - storage::FileSystemMountOption mount_option;
|
| - std::string cracked_id;
|
| - if (!context->CrackVirtualPath(virtual_path, &filesystem_id, &type,
|
| - &cracked_id, file_path, &mount_option)) {
|
| - *error = kInvalidParameters;
|
| - return false;
|
| - }
|
| -
|
| - // The file system API is only intended to operate on file entries that
|
| - // correspond to a native file, selected by the user so only allow file
|
| - // systems returned by the file system API or from a drag and drop operation.
|
| - if (type != storage::kFileSystemTypeNativeForPlatformApp &&
|
| - type != storage::kFileSystemTypeDragged) {
|
| - *error = kInvalidParameters;
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -} // namespace app_file_handler_util
|
| -
|
| -} // namespace extensions
|
|
|