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 |