Commit 3861521c authored by hidehiko@chromium.org's avatar hidehiko@chromium.org

Implement startCopy and cancelCopy.

This CL implements startCopy and cancelCopy of fileBrowserPrivate APIs.
Note that startCopy works now, but cancellation and progress reporting are not
supported yet.

BUG=279288
TEST=Ran unit_tests and tested manually.
R=kinaba@chromium.org

Review URL: https://codereview.chromium.org/23604042

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222007 0039d316-1c4b-4281-b951-d872f2087c98
parent b3c66eeb
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/file_browser_private.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "chromeos/login/login_state.h" #include "chromeos/login/login_state.h"
#include "chromeos/network/network_handler.h" #include "chromeos/network/network_handler.h"
...@@ -227,6 +228,15 @@ std::string MountTypeToString(chromeos::MountType type) { ...@@ -227,6 +228,15 @@ std::string MountTypeToString(chromeos::MountType type) {
return ""; return "";
} }
// Sends an event named |event_name| with arguments |event_args| to extensions.
void BroadcastEvent(Profile* profile,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args) {
extensions::ExtensionSystem::Get(profile)->event_router()->
BroadcastEvent(make_scoped_ptr(
new extensions::Event(event_name, event_args.Pass())));
}
} // namespace } // namespace
// Pass dummy value to JobInfo's constructor for make it default constructible. // Pass dummy value to JobInfo's constructor for make it default constructible.
...@@ -239,8 +249,7 @@ EventRouter::DriveJobInfoWithStatus::DriveJobInfoWithStatus( ...@@ -239,8 +249,7 @@ EventRouter::DriveJobInfoWithStatus::DriveJobInfoWithStatus(
: job_info(info), status(status) { : job_info(info), status(status) {
} }
EventRouter::EventRouter( EventRouter::EventRouter(Profile* profile)
Profile* profile)
: notifications_(new DesktopNotifications(profile)), : notifications_(new DesktopNotifications(profile)),
pref_change_registrar_(new PrefChangeRegistrar), pref_change_registrar_(new PrefChangeRegistrar),
profile_(profile), profile_(profile),
...@@ -406,6 +415,32 @@ void EventRouter::RemoveFileWatch(const base::FilePath& local_path, ...@@ -406,6 +415,32 @@ void EventRouter::RemoveFileWatch(const base::FilePath& local_path,
} }
} }
void EventRouter::OnCopyCompleted(
int copy_id, const GURL& url, base::PlatformFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
using extensions::api::file_browser_private::CopyProgressStatus;
namespace OnCopyProgress =
extensions::api::file_browser_private::OnCopyProgress;
CopyProgressStatus status;
if (error == base::PLATFORM_FILE_OK) {
// Send success event.
status.type = CopyProgressStatus::TYPE_SUCCESS;
status.url.reset(new std::string(url.spec()));
} else {
// Send error event.
status.type = CopyProgressStatus::TYPE_ERROR;
status.error.reset(
new int(fileapi::PlatformFileErrorToWebFileError(error)));
}
BroadcastEvent(
profile_,
extensions::event_names::kOnFileBrowserCopyProgress,
OnCopyProgress::Create(copy_id, status));
}
void EventRouter::OnDiskEvent(DiskMountManager::DiskEvent event, void EventRouter::OnDiskEvent(DiskMountManager::DiskEvent event,
const DiskMountManager::Disk* disk) { const DiskMountManager::Disk* disk) {
// Disk event is dispatched by VolumeManager now. Do nothing. // Disk event is dispatched by VolumeManager now. Do nothing.
...@@ -479,11 +514,11 @@ void EventRouter::NetworkManagerChanged() { ...@@ -479,11 +514,11 @@ void EventRouter::NetworkManagerChanged() {
NOTREACHED(); NOTREACHED();
return; return;
} }
scoped_ptr<extensions::Event> event(new extensions::Event(
BroadcastEvent(
profile_,
extensions::event_names::kOnFileBrowserDriveConnectionStatusChanged, extensions::event_names::kOnFileBrowserDriveConnectionStatusChanged,
scoped_ptr<ListValue>(new ListValue()))); make_scoped_ptr(new ListValue));
extensions::ExtensionSystem::Get(profile_)->event_router()->
BroadcastEvent(event.Pass());
} }
void EventRouter::DefaultNetworkChanged(const chromeos::NetworkState* network) { void EventRouter::DefaultNetworkChanged(const chromeos::NetworkState* network) {
...@@ -515,11 +550,10 @@ void EventRouter::OnFileManagerPrefsChanged() { ...@@ -515,11 +550,10 @@ void EventRouter::OnFileManagerPrefsChanged() {
return; return;
} }
scoped_ptr<extensions::Event> event(new extensions::Event( BroadcastEvent(
profile_,
extensions::event_names::kOnFileBrowserPreferencesChanged, extensions::event_names::kOnFileBrowserPreferencesChanged,
scoped_ptr<ListValue>(new ListValue()))); make_scoped_ptr(new ListValue));
extensions::ExtensionSystem::Get(profile_)->event_router()->
BroadcastEvent(event.Pass());
} }
void EventRouter::OnJobAdded(const drive::JobInfo& job_info) { void EventRouter::OnJobAdded(const drive::JobInfo& job_info) {
...@@ -641,11 +675,10 @@ void EventRouter::OnRefreshTokenInvalid() { ...@@ -641,11 +675,10 @@ void EventRouter::OnRefreshTokenInvalid() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Raise a DriveConnectionStatusChanged event to notify the status offline. // Raise a DriveConnectionStatusChanged event to notify the status offline.
scoped_ptr<extensions::Event> event(new extensions::Event( BroadcastEvent(
profile_,
extensions::event_names::kOnFileBrowserDriveConnectionStatusChanged, extensions::event_names::kOnFileBrowserDriveConnectionStatusChanged,
scoped_ptr<ListValue>(new ListValue()))); make_scoped_ptr(new ListValue));
extensions::ExtensionSystem::Get(profile_)->event_router()->
BroadcastEvent(event.Pass());
} }
void EventRouter::HandleFileWatchNotification(const base::FilePath& local_path, void EventRouter::HandleFileWatchNotification(const base::FilePath& local_path,
...@@ -736,10 +769,9 @@ void EventRouter::DispatchMountEvent( ...@@ -736,10 +769,9 @@ void EventRouter::DispatchMountEvent(
} }
} }
scoped_ptr<extensions::Event> extension_event(new extensions::Event( BroadcastEvent(profile_,
extensions::event_names::kOnFileBrowserMountCompleted, args.Pass())); extensions::event_names::kOnFileBrowserMountCompleted,
extensions::ExtensionSystem::Get(profile_)->event_router()-> args.Pass());
BroadcastEvent(extension_event.Pass());
} }
void EventRouter::ShowRemovableDeviceInFileManager( void EventRouter::ShowRemovableDeviceInFileManager(
......
...@@ -22,6 +22,10 @@ ...@@ -22,6 +22,10 @@
class PrefChangeRegistrar; class PrefChangeRegistrar;
class Profile; class Profile;
namespace base {
class ListValue;
}
namespace chromeos { namespace chromeos {
class NetworkState; class NetworkState;
} }
...@@ -66,6 +70,10 @@ class EventRouter ...@@ -66,6 +70,10 @@ class EventRouter
void RemoveFileWatch(const base::FilePath& local_path, void RemoveFileWatch(const base::FilePath& local_path,
const std::string& extension_id); const std::string& extension_id);
// Called when a copy task is completed.
void OnCopyCompleted(
int copy_id, const GURL& url, base::PlatformFileError error);
// DiskMountManager::Observer overrides. // DiskMountManager::Observer overrides.
virtual void OnDiskEvent( virtual void OnDiskEvent(
chromeos::disks::DiskMountManager::DiskEvent event, chromeos::disks::DiskMountManager::DiskEvent event,
......
...@@ -11,9 +11,11 @@ ...@@ -11,9 +11,11 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "base/posix/eintr_wrapper.h" #include "base/posix/eintr_wrapper.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/task_runner_util.h" #include "base/task_runner_util.h"
#include "base/threading/sequenced_worker_pool.h" #include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/drive/drive.pb.h" #include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/file_system_interface.h" #include "chrome/browser/chromeos/drive/file_system_interface.h"
#include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/chromeos/drive/file_system_util.h"
...@@ -23,6 +25,8 @@ ...@@ -23,6 +25,8 @@
#include "chrome/browser/chromeos/file_manager/fileapi_util.h" #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/fileapi/file_system_backend.h" #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/extensions/api/file_browser_private.h"
#include "chromeos/disks/disk_mount_manager.h" #include "chromeos/disks/disk_mount_manager.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/child_process_security_policy.h"
...@@ -32,6 +36,7 @@ ...@@ -32,6 +36,7 @@
#include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_file_util.h" #include "webkit/browser/fileapi/file_system_file_util.h"
#include "webkit/browser/fileapi/file_system_operation_context.h" #include "webkit/browser/fileapi/file_system_operation_context.h"
#include "webkit/browser/fileapi/file_system_operation_runner.h"
#include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/file_system_url.h"
#include "webkit/common/fileapi/file_system_types.h" #include "webkit/common/fileapi/file_system_types.h"
#include "webkit/common/fileapi/file_system_util.h" #include "webkit/common/fileapi/file_system_util.h"
...@@ -175,6 +180,79 @@ bool SetLastModifiedOnBlockingPool(const base::FilePath& local_path, ...@@ -175,6 +180,79 @@ bool SetLastModifiedOnBlockingPool(const base::FilePath& local_path,
return utime(local_path.value().c_str(), &times) == 0; return utime(local_path.value().c_str(), &times) == 0;
} }
// Notifies the copy completion to extensions via event router.
void NotifyCopyCompletion(
void* profile_id,
fileapi::FileSystemOperationRunner::OperationID operation_id,
const FileSystemURL& dest_url,
base::PlatformFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// |profile_id| needs to be checked with ProfileManager::IsValidProfile
// before using it.
Profile* profile = reinterpret_cast<Profile*>(profile_id);
if (!g_browser_process->profile_manager()->IsValidProfile(profile))
return;
file_manager::EventRouter* event_router =
file_manager::FileBrowserPrivateAPI::Get(profile)->event_router();
event_router->OnCopyCompleted(operation_id, dest_url.ToGURL(), error);
}
// Callback invoked upon completion of Copy() (regardless of succeeded or
// failed).
void OnCopyCompleted(
void* profile_id,
fileapi::FileSystemOperationRunner::OperationID* operation_id,
const FileSystemURL& dest_url,
base::PlatformFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&NotifyCopyCompletion,
profile_id, *operation_id, dest_url, error));
}
// Starts the copy operation via FileSystemOperationRunner.
fileapi::FileSystemOperationRunner::OperationID StartCopyOnIOThread(
void* profile_id,
scoped_refptr<fileapi::FileSystemContext> file_system_context,
const FileSystemURL& source_url,
const FileSystemURL& dest_url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Note: |operation_id| is owned by the callback for
// FileSystemOperationRunner::Copy(). It is always called in the next message
// loop or later, so at least during this invocation it should alive.
fileapi::FileSystemOperationRunner::OperationID* operation_id =
new fileapi::FileSystemOperationRunner::OperationID;
*operation_id = file_system_context->operation_runner()->Copy(
source_url, dest_url,
base::Bind(&OnCopyCompleted,
profile_id, base::Owned(operation_id), dest_url));
return *operation_id;
}
void OnCopyCancelled(base::PlatformFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// We just ignore the status if the copy is actually cancelled or not,
// because failing cancellation means the operation is not running now.
DLOG_IF(WARNING, error != base::PLATFORM_FILE_OK)
<< "Failed to cancel copy: " << error;
}
// Cancels the running copy operation identified by |operation_id|.
void CancelCopyOnIOThread(
scoped_refptr<fileapi::FileSystemContext> file_system_context,
fileapi::FileSystemOperationRunner::OperationID operation_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
file_system_context->operation_runner()->Cancel(
operation_id, base::Bind(&OnCopyCancelled));
}
} // namespace } // namespace
FileBrowserPrivateRequestFileSystemFunction:: FileBrowserPrivateRequestFileSystemFunction::
...@@ -631,9 +709,49 @@ FileBrowserPrivateStartCopyFunction::~FileBrowserPrivateStartCopyFunction() { ...@@ -631,9 +709,49 @@ FileBrowserPrivateStartCopyFunction::~FileBrowserPrivateStartCopyFunction() {
} }
bool FileBrowserPrivateStartCopyFunction::RunImpl() { bool FileBrowserPrivateStartCopyFunction::RunImpl() {
// TODO(hidehiko): Implement startCopy function. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
NOTIMPLEMENTED();
return false; using extensions::api::file_browser_private::StartCopy::Params;
const scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
if (params->source_url.empty() || params->parent.empty() ||
params->new_name.empty()) {
error_ = base::IntToString(fileapi::PlatformFileErrorToWebFileError(
base::PLATFORM_FILE_ERROR_INVALID_URL));
return false;
}
scoped_refptr<fileapi::FileSystemContext> file_system_context =
file_manager::util::GetFileSystemContextForRenderViewHost(
profile(), render_view_host());
fileapi::FileSystemURL source_url(
file_system_context->CrackURL(GURL(params->source_url)));
fileapi::FileSystemURL dest_url(file_system_context->CrackURL(
GURL(params->parent + "/" + params->new_name)));
if (!source_url.is_valid() || !dest_url.is_valid()) {
error_ = base::IntToString(fileapi::PlatformFileErrorToWebFileError(
base::PLATFORM_FILE_ERROR_INVALID_URL));
return false;
}
return BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::IO,
FROM_HERE,
base::Bind(&StartCopyOnIOThread,
profile(), file_system_context, source_url, dest_url),
base::Bind(&FileBrowserPrivateStartCopyFunction::RunAfterStartCopy,
this));
}
void FileBrowserPrivateStartCopyFunction::RunAfterStartCopy(
int operation_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
SetResult(Value::CreateIntegerValue(operation_id));
SendResponse(true);
} }
FileBrowserPrivateCancelCopyFunction::FileBrowserPrivateCancelCopyFunction() { FileBrowserPrivateCancelCopyFunction::FileBrowserPrivateCancelCopyFunction() {
...@@ -643,9 +761,23 @@ FileBrowserPrivateCancelCopyFunction::~FileBrowserPrivateCancelCopyFunction() { ...@@ -643,9 +761,23 @@ FileBrowserPrivateCancelCopyFunction::~FileBrowserPrivateCancelCopyFunction() {
} }
bool FileBrowserPrivateCancelCopyFunction::RunImpl() { bool FileBrowserPrivateCancelCopyFunction::RunImpl() {
// TODO(hidehiko): Implement cancelCopy function. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
NOTIMPLEMENTED();
return false; using extensions::api::file_browser_private::CancelCopy::Params;
const scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
scoped_refptr<fileapi::FileSystemContext> file_system_context =
file_manager::util::GetFileSystemContextForRenderViewHost(
profile(), render_view_host());
// We don't much take care about the result of cancellation.
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&CancelCopyOnIOThread, file_system_context, params->copy_id));
SendResponse(true);
return true;
} }
} // namespace extensions } // namespace extensions
...@@ -234,6 +234,10 @@ class FileBrowserPrivateStartCopyFunction ...@@ -234,6 +234,10 @@ class FileBrowserPrivateStartCopyFunction
// AsyncExtensionFunction overrides. // AsyncExtensionFunction overrides.
virtual bool RunImpl() OVERRIDE; virtual bool RunImpl() OVERRIDE;
private:
// Part of RunImpl(). Called after Copy() is started on IO thread.
void RunAfterStartCopy(int operation_id);
}; };
// Implements the chrome.fileBrowserPrivate.cancelCopy method. // Implements the chrome.fileBrowserPrivate.cancelCopy method.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment