| Index: chrome/browser/extensions/api/extfs/extfs_api.cc
|
| diff --git a/chrome/browser/extensions/api/extfs/extfs_api.cc b/chrome/browser/extensions/api/extfs/extfs_api.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..865818e29f9b870a305bb1ddc032af538a6ed170
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/api/extfs/extfs_api.cc
|
| @@ -0,0 +1,605 @@
|
| +// Copyright 2013 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/extensions/api/extfs/extfs_api.h"
|
| +
|
| +#include "base/compiler_specific.h"
|
| +#include "base/file_util.h"
|
| +#include "chrome/browser/extensions/event_names.h"
|
| +#include "chrome/browser/extensions/event_router.h"
|
| +#include "chrome/browser/extensions/extension_system.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/common/extensions/api/extfs.h"
|
| +#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
|
| +#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
|
| +#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
|
| +#include "content/public/browser/browser_context.h"
|
| +#include "webkit/browser/blob/file_stream_reader.h"
|
| +#include "webkit/browser/fileapi/external_mount_points.h"
|
| +#include "webkit/browser/fileapi/file_system_url.h"
|
| +#include "webkit/browser/fileapi/remote_file_system_proxy.h"
|
| +#include "webkit/common/blob/shareable_file_reference.h"
|
| +#include "webkit/common/fileapi/directory_entry.h"
|
| +
|
| +using content::BrowserThread;
|
| +
|
| +namespace extensions {
|
| +
|
| +namespace {
|
| +
|
| +// Converts api::extfs::FileError to base::PlatformFileError.
|
| +base::PlatformFileError ToPlatformFileError(api::extfs::FileError error) {
|
| + switch (error) {
|
| + case api::extfs::FILE_ERROR_NONE:
|
| + break;
|
| + case api::extfs::FILE_ERROR_OK:
|
| + return base::PLATFORM_FILE_OK;
|
| + case api::extfs::FILE_ERROR_ERROR_FAILED:
|
| + return base::PLATFORM_FILE_ERROR_FAILED;
|
| + case api::extfs::FILE_ERROR_ERROR_IN_USE:
|
| + return base::PLATFORM_FILE_ERROR_IN_USE;
|
| + case api::extfs::FILE_ERROR_ERROR_EXISTS:
|
| + return base::PLATFORM_FILE_ERROR_EXISTS;
|
| + case api::extfs::FILE_ERROR_ERROR_NOT_FOUND:
|
| + return base::PLATFORM_FILE_ERROR_NOT_FOUND;
|
| + case api::extfs::FILE_ERROR_ERROR_ACCESS_DENIED:
|
| + return base::PLATFORM_FILE_ERROR_ACCESS_DENIED;
|
| + case api::extfs::FILE_ERROR_ERROR_TOO_MANY_OPENED:
|
| + return base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED;
|
| + case api::extfs::FILE_ERROR_ERROR_NO_MEMORY:
|
| + return base::PLATFORM_FILE_ERROR_NO_MEMORY;
|
| + case api::extfs::FILE_ERROR_ERROR_NO_SPACE:
|
| + return base::PLATFORM_FILE_ERROR_NO_SPACE;
|
| + case api::extfs::FILE_ERROR_ERROR_NOT_A_DIRECTORY:
|
| + return base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY;
|
| + case api::extfs::FILE_ERROR_ERROR_INVALID_OPERATION:
|
| + return base::PLATFORM_FILE_ERROR_INVALID_OPERATION;
|
| + case api::extfs::FILE_ERROR_ERROR_SECURITY:
|
| + return base::PLATFORM_FILE_ERROR_SECURITY;
|
| + case api::extfs::FILE_ERROR_ERROR_ABORT:
|
| + return base::PLATFORM_FILE_ERROR_ABORT;
|
| + case api::extfs::FILE_ERROR_ERROR_NOT_A_FILE:
|
| + return base::PLATFORM_FILE_ERROR_NOT_A_FILE;
|
| + case api::extfs::FILE_ERROR_ERROR_NOT_EMPTY:
|
| + return base::PLATFORM_FILE_ERROR_NOT_EMPTY;
|
| + case api::extfs::FILE_ERROR_ERROR_INVALID_URL:
|
| + return base::PLATFORM_FILE_ERROR_INVALID_URL;
|
| + case api::extfs::FILE_ERROR_ERROR_IO:
|
| + return base::PLATFORM_FILE_ERROR_IO;
|
| + case api::extfs::FILE_ERROR_ERROR_MAX:
|
| + return base::PLATFORM_FILE_ERROR_MAX;
|
| + }
|
| + NOTREACHED();
|
| + return base::PLATFORM_FILE_ERROR_FAILED;
|
| +}
|
| +
|
| +void CreateTemporaryFile(
|
| + scoped_ptr<std::string> content,
|
| + base::PlatformFileError* error,
|
| + base::PlatformFileInfo* file_info,
|
| + base::FilePath* file_path) {
|
| + DCHECK(content);
|
| + DCHECK(error);
|
| + DCHECK(file_info);
|
| + DCHECK(file_path);
|
| +
|
| + *error = base::PLATFORM_FILE_ERROR_FAILED;
|
| +
|
| +
|
| + if (!file_util::CreateTemporaryFile(file_path))
|
| + return;
|
| +
|
| + if (file_util::WriteFile(*file_path, content->data(), content->size()) !=
|
| + static_cast<int>(content->size()))
|
| + return;
|
| +
|
| + if (!file_util::GetFileInfo(*file_path, file_info))
|
| + return;
|
| +
|
| + *error = base::PLATFORM_FILE_OK;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +class ExtfsProxy : public fileapi::RemoteFileSystemProxyInterface {
|
| + public:
|
| + ExtfsProxy(Profile* profile)
|
| + : profile_(profile),
|
| + request_id_(0) {
|
| + }
|
| +
|
| + bool AddMountPoint(const std::string& mount_point,
|
| + const std::string& extension_id) {
|
| + if (mount_point_to_extension_id_map_.count(mount_point) > 0)
|
| + return false;
|
| + mount_point_to_extension_id_map_[mount_point] = extension_id;
|
| + return true;
|
| + }
|
| +
|
| + std::string GetExtensionIdFromPath(const base::FilePath& path) {
|
| + std::vector<base::FilePath::StringType> components;
|
| + path.GetComponents(&components);
|
| + DCHECK_LE(2U, components.size());
|
| + DCHECK_EQ(FILE_PATH_LITERAL("/"), components[0]);
|
| + const std::string mount_point =
|
| + base::FilePath(components[1]).AsUTF8Unsafe();
|
| +
|
| + LOG(ERROR) << "@@ mount_point: " << mount_point;
|
| + DCHECK_EQ(1U, mount_point_to_extension_id_map_.count(mount_point));
|
| + return mount_point_to_extension_id_map_[mount_point];
|
| + }
|
| +
|
| + // fileapi::RemoteFileSystemProxyInterface overrides.
|
| + virtual void GetFileInfo(
|
| + const fileapi::FileSystemURL& url,
|
| + const fileapi::FileSystemOperation::GetMetadataCallback& callback)
|
| + OVERRIDE {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + LOG(ERROR) << "@@ " << __FUNCTION__ << ": " << url.path().value();
|
| + const std::string extension_id = GetExtensionIdFromPath(url.path());
|
| + DCHECK(!extension_id.empty());
|
| +
|
| + get_metadata_callback_map_[request_id_] = callback;
|
| + scoped_ptr<base::ListValue> values(new ListValue());
|
| + values->AppendInteger(request_id_);
|
| + values->AppendString(url.path().value());
|
| + scoped_ptr<Event> event(new Event(event_names::kOnEntryRequested,
|
| + values.Pass()));
|
| +
|
| + GetEventRouter()->DispatchEventToExtension(extension_id, event.Pass());
|
| + ++request_id_;
|
| + }
|
| +
|
| + virtual void Copy(
|
| + const fileapi::FileSystemURL& src_url,
|
| + const fileapi::FileSystemURL& dest_url,
|
| + const fileapi::FileSystemOperation::StatusCallback& callback)
|
| + OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual void Move(
|
| + const fileapi::FileSystemURL& src_url,
|
| + const fileapi::FileSystemURL& dest_url,
|
| + const fileapi::FileSystemOperation::StatusCallback& callback)
|
| + OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual void ReadDirectory(
|
| + const fileapi::FileSystemURL& url,
|
| + const fileapi::FileSystemOperation::ReadDirectoryCallback& callback)
|
| + OVERRIDE {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + LOG(ERROR) << "@@ " << __FUNCTION__ << ": " << url.path().value();
|
| + const std::string extension_id = GetExtensionIdFromPath(url.path());
|
| + DCHECK(!extension_id.empty());
|
| +
|
| + read_directory_callback_map_[request_id_] = callback;
|
| + scoped_ptr<base::ListValue> values(new ListValue());
|
| + values->AppendInteger(request_id_);
|
| + values->AppendString(url.path().value());
|
| + scoped_ptr<Event> event(
|
| + new Event(event_names::kOnDirectoryEntriesRequested,
|
| + values.Pass()));
|
| +
|
| + GetEventRouter()->DispatchEventToExtension(extension_id, event.Pass());
|
| + ++request_id_;
|
| + }
|
| +
|
| + virtual void Remove(
|
| + const fileapi::FileSystemURL& url, bool recursive,
|
| + const fileapi::FileSystemOperation::StatusCallback& callback)
|
| + OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual void CreateDirectory(
|
| + const fileapi::FileSystemURL& file_url,
|
| + bool exclusive,
|
| + bool recursive,
|
| + const fileapi::FileSystemOperation::StatusCallback& callback)
|
| + OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual void CreateFile(
|
| + const fileapi::FileSystemURL& file_url,
|
| + bool exclusive,
|
| + const fileapi::FileSystemOperation::StatusCallback& callback)
|
| + OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual void Truncate(
|
| + const fileapi::FileSystemURL& file_url, int64 length,
|
| + const fileapi::FileSystemOperation::StatusCallback& callback)
|
| + OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual void CreateSnapshotFile(
|
| + const fileapi::FileSystemURL& url,
|
| + const fileapi::FileSystemOperation::SnapshotFileCallback& callback)
|
| + OVERRIDE {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + LOG(ERROR) << "@@ " << __FUNCTION__ << ": " << url.path().value();
|
| + const std::string extension_id = GetExtensionIdFromPath(url.path());
|
| + DCHECK(!extension_id.empty());
|
| +
|
| + snapshot_file_callback_map_[request_id_] = callback;
|
| + scoped_ptr<base::ListValue> values(new ListValue());
|
| + values->AppendInteger(request_id_);
|
| + values->AppendString(url.path().value());
|
| + scoped_ptr<Event> event(
|
| + new Event(event_names::kOnSnapshotRequested, values.Pass()));
|
| +
|
| + GetEventRouter()->DispatchEventToExtension(extension_id, event.Pass());
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__ << ": " << request_id_;
|
| + ++request_id_;
|
| + }
|
| +
|
| + virtual void CreateWritableSnapshotFile(
|
| + const fileapi::FileSystemURL& url,
|
| + const fileapi::WritableSnapshotFile& callback) OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual void OpenFile(
|
| + const fileapi::FileSystemURL& url,
|
| + int file_flags,
|
| + base::ProcessHandle peer_handle,
|
| + const OpenFileCallback& callback) OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual void NotifyCloseFile(const fileapi::FileSystemURL& url) OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual void TouchFile(
|
| + const fileapi::FileSystemURL& url,
|
| + const base::Time& last_access_time,
|
| + const base::Time& last_modified_time,
|
| + const fileapi::FileSystemOperation::StatusCallback& callback)
|
| + OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + }
|
| +
|
| + virtual scoped_ptr<webkit_blob::FileStreamReader> CreateFileStreamReader(
|
| + base::SequencedTaskRunner* file_task_runner,
|
| + const fileapi::FileSystemURL& url,
|
| + int64 offset,
|
| + const base::Time& expected_modification_time) OVERRIDE {
|
| + NOTREACHED() << "@@ not implemented";
|
| + return scoped_ptr<webkit_blob::FileStreamReader>();
|
| + }
|
| +
|
| + void DidGetFileInfo(int request_id,
|
| + const base::PlatformFileError file_error,
|
| + const base::PlatformFileInfo& file_info) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
|
| +
|
| + GetMetadataCallbackMap::iterator iter =
|
| + get_metadata_callback_map_.find(request_id);
|
| + DCHECK(iter != get_metadata_callback_map_.end());
|
| + iter->second.Run(file_error, file_info);
|
| + get_metadata_callback_map_.erase(iter);
|
| + }
|
| +
|
| + void DidReadDirectory(int request_id,
|
| + const base::PlatformFileError file_error,
|
| + const std::vector<fileapi::DirectoryEntry>& entries) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
|
| +
|
| + ReadDirectoryCallbackMap::iterator iter =
|
| + read_directory_callback_map_.find(request_id);
|
| + DCHECK(iter != read_directory_callback_map_.end());
|
| + iter->second.Run(file_error, entries, false /* has more */);
|
| + read_directory_callback_map_.erase(iter);
|
| + }
|
| +
|
| + void DidCreateSnapshotFile(int request_id,
|
| + base::PlatformFileError file_error,
|
| + const base::PlatformFileInfo& file_info,
|
| + const base::FilePath& file_path) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__ << ": " << request_id;
|
| +
|
| + SnapshotFileCallbackMap::iterator iter =
|
| + snapshot_file_callback_map_.find(request_id);
|
| + DCHECK(iter != snapshot_file_callback_map_.end());
|
| +
|
| + // Create a reference so that the local file is removed later.
|
| + scoped_refptr<webkit_blob::ShareableFileReference> reference =
|
| + webkit_blob::ShareableFileReference::GetOrCreate(
|
| + file_path,
|
| + webkit_blob::ShareableFileReference::DELETE_ON_FINAL_RELEASE,
|
| + BrowserThread::GetMessageLoopProxyForThread(
|
| + BrowserThread::FILE).get());
|
| +
|
| + iter->second.Run(file_error, file_info, file_path, reference);
|
| + snapshot_file_callback_map_.erase(iter);
|
| + }
|
| +
|
| + protected:
|
| + virtual ~ExtfsProxy() {
|
| + }
|
| +
|
| + private:
|
| + EventRouter* GetEventRouter() {
|
| + return ExtensionSystem::Get(profile_)->event_router();
|
| + }
|
| +
|
| + typedef std::map<int, fileapi::FileSystemOperation::GetMetadataCallback>
|
| + GetMetadataCallbackMap;
|
| + typedef std::map<int, fileapi::FileSystemOperation::ReadDirectoryCallback>
|
| + ReadDirectoryCallbackMap;
|
| + typedef std::map<int, fileapi::FileSystemOperation::SnapshotFileCallback>
|
| + SnapshotFileCallbackMap;
|
| +
|
| + Profile* profile_;
|
| + int request_id_;
|
| + std::map<std::string, std::string> mount_point_to_extension_id_map_;
|
| + GetMetadataCallbackMap get_metadata_callback_map_;
|
| + ReadDirectoryCallbackMap read_directory_callback_map_;
|
| + SnapshotFileCallbackMap snapshot_file_callback_map_;
|
| +};
|
| +
|
| +class ExtfsService : public BrowserContextKeyedService {
|
| + public:
|
| + ExtfsService(Profile* profile)
|
| + : extfs_proxy_(new ExtfsProxy(profile)) {
|
| + }
|
| +
|
| + virtual ~ExtfsService() {
|
| + }
|
| +
|
| + scoped_refptr<ExtfsProxy> extfs_proxy() {
|
| + return extfs_proxy_;
|
| + }
|
| +
|
| + private:
|
| + friend class ExtfsServiceFactory;
|
| + scoped_refptr<ExtfsProxy> extfs_proxy_;
|
| +};
|
| +
|
| +class ExtfsServiceFactory : public BrowserContextKeyedServiceFactory {
|
| + public:
|
| + static ExtfsService* GetForProfile(Profile* profile) {
|
| + return static_cast<ExtfsService*>(
|
| + GetInstance()->GetServiceForBrowserContext(profile, true));
|
| + }
|
| +
|
| + static ExtfsServiceFactory* GetInstance() {
|
| + return Singleton<ExtfsServiceFactory>::get();
|
| + }
|
| +
|
| + private:
|
| + friend struct DefaultSingletonTraits<ExtfsServiceFactory>;
|
| +
|
| + ExtfsServiceFactory()
|
| + : BrowserContextKeyedServiceFactory(
|
| + "ExtfsService",
|
| + BrowserContextDependencyManager::GetInstance()) {
|
| + }
|
| +
|
| + virtual ~ExtfsServiceFactory() {}
|
| +
|
| + // BrowserContextKeyedServiceFactory overrides:
|
| + virtual BrowserContextKeyedService*
|
| + BuildServiceInstanceFor(content::BrowserContext* context) const OVERRIDE {
|
| + Profile* profile = static_cast<Profile*>(context);
|
| + return new ExtfsService(profile);
|
| + }
|
| +};
|
| +
|
| +scoped_refptr<ExtfsProxy> GetExtfsProxy(Profile* profile) {
|
| + return ExtfsServiceFactory::GetForProfile(profile)->extfs_proxy();
|
| +}
|
| +
|
| +bool ExtfsAddMountPointFunction::RunImpl() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + scoped_ptr<api::extfs::AddMountPoint::Params> params(
|
| + api::extfs::AddMountPoint::Params::Create(*args_));
|
| + EXTENSION_FUNCTION_VALIDATE(params.get());
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__
|
| + << " mount point: " << params->mount_point;
|
| +
|
| + scoped_refptr<ExtfsProxy> extfs_proxy = GetExtfsProxy(profile());
|
| +
|
| + if (!extfs_proxy->AddMountPoint(params->mount_point, extension_id())) {
|
| + NOTREACHED();
|
| + }
|
| +
|
| + fileapi::ExternalMountPoints* mount_points =
|
| + content::BrowserContext::GetMountPoints(profile_);
|
| + DCHECK(mount_points);
|
| +
|
| + bool success = mount_points->RegisterRemoteFileSystem(
|
| + params->mount_point,
|
| + // TODO(satorux): This file system type is wrong.
|
| + fileapi::kFileSystemTypeDrive,
|
| + extfs_proxy,
|
| + base::FilePath::FromUTF8Unsafe("/" + params->mount_point));
|
| + DCHECK(success);
|
| +
|
| + SetResult(base::Value::CreateStringValue(
|
| + api::extfs::ToString(api::extfs::FILE_ERROR_OK)));
|
| + SendResponse(true);
|
| + return true;
|
| +}
|
| +
|
| +bool ExtfsReturnEntryFunction::RunImpl() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
|
| +
|
| + scoped_ptr<api::extfs::ReturnEntry::Params> params(
|
| + api::extfs::ReturnEntry::Params::Create(*args_));
|
| +
|
| + EXTENSION_FUNCTION_VALIDATE(params.get());
|
| + base::PlatformFileInfo file_info;
|
| + file_info.is_directory = params->entry.is_directory;
|
| +
|
| + scoped_refptr<ExtfsProxy> extfs_proxy = GetExtfsProxy(profile());
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&ExtfsProxy::DidGetFileInfo,
|
| + extfs_proxy,
|
| + params->request_id,
|
| + ToPlatformFileError(params->error_code),
|
| + file_info));
|
| + return true;
|
| +}
|
| +
|
| +bool ExtfsReturnEntriesFunction::RunImpl() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
|
| +
|
| + scoped_ptr<api::extfs::ReturnEntries::Params> params(
|
| + api::extfs::ReturnEntries::Params::Create(*args_));
|
| +
|
| + EXTENSION_FUNCTION_VALIDATE(params.get());
|
| + std::vector<fileapi::DirectoryEntry> entries;
|
| + for (size_t i = 0; i < params->entries.size(); ++i) {
|
| + fileapi::DirectoryEntry entry;
|
| + entry.name = params->entries[i]->name;
|
| + entry.is_directory = params->entries[i]->is_directory;
|
| + entry.size = params->entries[i]->size;
|
| + entries.push_back(entry);
|
| + }
|
| +
|
| + scoped_refptr<ExtfsProxy> extfs_proxy = GetExtfsProxy(profile());
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&ExtfsProxy::DidReadDirectory,
|
| + extfs_proxy,
|
| + params->request_id,
|
| + ToPlatformFileError(params->error_code),
|
| + entries));
|
| + return true;
|
| +}
|
| +
|
| +ExtfsReturnSnapshotFunction::ExtfsReturnSnapshotFunction()
|
| + : url_fetcher_(NULL),
|
| + request_id_(0) {
|
| +}
|
| +
|
| +bool ExtfsReturnSnapshotFunction::RunImpl() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
|
| +
|
| + // Don't use ReturnSnapshot::Params::Create() as we'll take a blob URL
|
| + // instead of a blob object. The conversion is done in the custom binding.
|
| + std::string error_code_as_string;
|
| + // TODO(satorux): Revoke this URL later.
|
| + // blob_storage_context->controller()->RemoveBlob(url);
|
| + std::string blob_url;
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id_));
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &error_code_as_string));
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &blob_url));
|
| +
|
| + const base::PlatformFileError error_code =
|
| + ToPlatformFileError(api::extfs::ParseFileError(error_code_as_string));
|
| +
|
| + if (error_code != base::PLATFORM_FILE_OK) {
|
| + scoped_refptr<ExtfsProxy> extfs_proxy = GetExtfsProxy(profile());
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&ExtfsProxy::DidCreateSnapshotFile,
|
| + extfs_proxy,
|
| + request_id_,
|
| + error_code,
|
| + base::PlatformFileInfo(),
|
| + base::FilePath()));
|
| + return true;
|
| + }
|
| +
|
| + // TODO(satorux): We should bypass this if the blob contains just a
|
| + // single file. It's a waste to copy a file here.
|
| + url_fetcher_ = net::URLFetcher::Create(
|
| + GURL(blob_url),
|
| + net::URLFetcher::GET,
|
| + this);
|
| + // Add the reference count so this object outlives |url_fetcher_|.
|
| + // This will be released in OnURLFetchComplete().
|
| + AddRef();
|
| +
|
| + url_fetcher_->SetRequestContext(profile_->GetRequestContext());
|
| + url_fetcher_->Start();
|
| + return true;
|
| +}
|
| +
|
| +void ExtfsReturnSnapshotFunction::OnURLFetchComplete(
|
| + const net::URLFetcher* source) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
|
| +
|
| + if (source->GetResponseCode() != 200) {
|
| + scoped_refptr<ExtfsProxy> extfs_proxy = GetExtfsProxy(profile());
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&ExtfsProxy::DidCreateSnapshotFile,
|
| + extfs_proxy,
|
| + request_id_,
|
| + base::PLATFORM_FILE_ERROR_FAILED,
|
| + base::PlatformFileInfo(),
|
| + base::FilePath()));
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<std::string> content(new std::string);
|
| + source->GetResponseAsString(content.get());
|
| + delete url_fetcher_;
|
| +
|
| + // PostTaskAndReplyWithResult() is not used, in favor of not exposing a
|
| + // struct name in .h file. Not a big deal though.
|
| + base::PlatformFileError* file_error = new base::PlatformFileError;
|
| + base::PlatformFileInfo* file_info = new base::PlatformFileInfo;
|
| + base::FilePath* file_path = new base::FilePath;
|
| + BrowserThread::PostTaskAndReply(
|
| + BrowserThread::FILE,
|
| + FROM_HERE,
|
| + base::Bind(&CreateTemporaryFile,
|
| + base::Passed(&content),
|
| + file_error,
|
| + file_info,
|
| + file_path),
|
| + base::Bind(&ExtfsReturnSnapshotFunction::DidCreateTemporaryFile,
|
| + this,
|
| + base::Owned(file_error),
|
| + base::Owned(file_info),
|
| + base::Owned(file_path)));
|
| +
|
| + // This matches AddRef() in RunImpl().
|
| + Release();
|
| +}
|
| +
|
| +void ExtfsReturnSnapshotFunction::DidCreateTemporaryFile(
|
| + base::PlatformFileError* file_error,
|
| + base::PlatformFileInfo* file_info,
|
| + base::FilePath* file_path) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
|
| +
|
| + scoped_refptr<ExtfsProxy> extfs_proxy = GetExtfsProxy(profile());
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&ExtfsProxy::DidCreateSnapshotFile,
|
| + extfs_proxy,
|
| + request_id_,
|
| + *file_error,
|
| + *file_info,
|
| + *file_path));
|
| +}
|
| +
|
| +} // namespace extensions
|
|
|