| Index: chrome/browser/chromeos/drive/sync/entry_update_performer.cc
|
| diff --git a/chrome/browser/chromeos/drive/sync/entry_update_performer.cc b/chrome/browser/chromeos/drive/sync/entry_update_performer.cc
|
| deleted file mode 100644
|
| index f3b24a942a5fa09be0505d6a37cf2e1d0524123e..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/chromeos/drive/sync/entry_update_performer.cc
|
| +++ /dev/null
|
| @@ -1,450 +0,0 @@
|
| -// 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/chromeos/drive/sync/entry_update_performer.h"
|
| -
|
| -#include <set>
|
| -
|
| -#include "base/callback_helpers.h"
|
| -#include "base/files/file_util.h"
|
| -#include "chrome/browser/chromeos/drive/sync/entry_revert_performer.h"
|
| -#include "chrome/browser/chromeos/drive/sync/remove_performer.h"
|
| -#include "components/drive/change_list_loader.h"
|
| -#include "components/drive/drive.pb.h"
|
| -#include "components/drive/file_cache.h"
|
| -#include "components/drive/file_change.h"
|
| -#include "components/drive/file_system/operation_delegate.h"
|
| -#include "components/drive/file_system_core_util.h"
|
| -#include "components/drive/job_scheduler.h"
|
| -#include "components/drive/resource_metadata.h"
|
| -#include "google_apis/drive/drive_api_parser.h"
|
| -
|
| -namespace drive {
|
| -namespace internal {
|
| -
|
| -struct EntryUpdatePerformer::LocalState {
|
| - LocalState() : cache_file_size(0), should_content_update(false) {}
|
| -
|
| - ResourceEntry entry;
|
| - ResourceEntry parent_entry;
|
| - base::FilePath drive_file_path;
|
| - base::FilePath cache_file_path;
|
| - int64 cache_file_size;
|
| - bool should_content_update;
|
| -};
|
| -
|
| -namespace {
|
| -
|
| -struct PropertyCompare {
|
| - bool operator()(const drive::Property& x, const drive::Property& y) const {
|
| - if (x.key() < y.key())
|
| - return true;
|
| - if (x.key() > y.key())
|
| - return false;
|
| - if (x.value() < y.value())
|
| - return true;
|
| - if (y.value() > y.value())
|
| - return false;
|
| - return x.visibility() < y.visibility();
|
| - }
|
| -};
|
| -
|
| -// Looks up ResourceEntry for source entry and its parent.
|
| -FileError PrepareUpdate(ResourceMetadata* metadata,
|
| - FileCache* cache,
|
| - const std::string& local_id,
|
| - EntryUpdatePerformer::LocalState* local_state) {
|
| - FileError error = metadata->GetResourceEntryById(local_id,
|
| - &local_state->entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - error = metadata->GetResourceEntryById(local_state->entry.parent_local_id(),
|
| - &local_state->parent_entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - error = metadata->GetFilePath(local_id, &local_state->drive_file_path);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - if (!local_state->entry.file_info().is_directory() &&
|
| - !local_state->entry.file_specific_info().cache_state().is_present() &&
|
| - local_state->entry.resource_id().empty()) {
|
| - // Locally created file with no cache file, store an empty file.
|
| - base::FilePath empty_file;
|
| - if (!base::CreateTemporaryFile(&empty_file))
|
| - return FILE_ERROR_FAILED;
|
| - error = cache->Store(local_id, std::string(), empty_file,
|
| - FileCache::FILE_OPERATION_MOVE);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - error = metadata->GetResourceEntryById(local_id, &local_state->entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - }
|
| -
|
| - // Check if content update is needed or not.
|
| - if (local_state->entry.file_specific_info().cache_state().is_dirty() &&
|
| - !cache->IsOpenedForWrite(local_id)) {
|
| - // Update cache entry's MD5 if needed.
|
| - if (local_state->entry.file_specific_info().cache_state().md5().empty()) {
|
| - error = cache->UpdateMd5(local_id);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - error = metadata->GetResourceEntryById(local_id, &local_state->entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - }
|
| -
|
| - if (local_state->entry.file_specific_info().cache_state().md5() ==
|
| - local_state->entry.file_specific_info().md5()) {
|
| - error = cache->ClearDirty(local_id);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - } else {
|
| - error = cache->GetFile(local_id, &local_state->cache_file_path);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - const bool result = base::GetFileSize(local_state->cache_file_path,
|
| - &local_state->cache_file_size);
|
| - if (!result)
|
| - return FILE_ERROR_FAILED;
|
| - local_state->should_content_update = true;
|
| - }
|
| - }
|
| -
|
| - // Update metadata_edit_state.
|
| - switch (local_state->entry.metadata_edit_state()) {
|
| - case ResourceEntry::CLEAN: // Nothing to do.
|
| - case ResourceEntry::SYNCING: // Error during the last update. Go ahead.
|
| - break;
|
| -
|
| - case ResourceEntry::DIRTY:
|
| - local_state->entry.set_metadata_edit_state(ResourceEntry::SYNCING);
|
| - error = metadata->RefreshEntry(local_state->entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - break;
|
| - }
|
| - return FILE_ERROR_OK;
|
| -}
|
| -
|
| -FileError FinishUpdate(ResourceMetadata* metadata,
|
| - FileCache* cache,
|
| - scoped_ptr<EntryUpdatePerformer::LocalState> local_state,
|
| - scoped_ptr<google_apis::FileResource> file_resource,
|
| - FileChange* changed_files) {
|
| - ResourceEntry entry;
|
| - FileError error =
|
| - metadata->GetResourceEntryById(local_state->entry.local_id(), &entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| -
|
| - // When creating new entries, update check may add a new entry with the same
|
| - // resource ID before us. If such an entry exists, remove it.
|
| - std::string existing_local_id;
|
| - error =
|
| - metadata->GetIdByResourceId(file_resource->file_id(), &existing_local_id);
|
| -
|
| - switch (error) {
|
| - case FILE_ERROR_OK:
|
| - if (existing_local_id != local_state->entry.local_id()) {
|
| - base::FilePath existing_entry_path;
|
| - error = metadata->GetFilePath(existing_local_id, &existing_entry_path);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - error = metadata->RemoveEntry(existing_local_id);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - changed_files->Update(existing_entry_path, entry,
|
| - FileChange::CHANGE_TYPE_DELETE);
|
| - }
|
| - break;
|
| - case FILE_ERROR_NOT_FOUND:
|
| - break;
|
| - default:
|
| - return error;
|
| - }
|
| -
|
| - // Update metadata_edit_state and MD5.
|
| - switch (entry.metadata_edit_state()) {
|
| - case ResourceEntry::CLEAN: // Nothing to do.
|
| - case ResourceEntry::DIRTY: // Entry was edited again during the update.
|
| - break;
|
| -
|
| - case ResourceEntry::SYNCING:
|
| - entry.set_metadata_edit_state(ResourceEntry::CLEAN);
|
| - break;
|
| - }
|
| - if (!entry.file_info().is_directory())
|
| - entry.mutable_file_specific_info()->set_md5(file_resource->md5_checksum());
|
| - entry.set_resource_id(file_resource->file_id());
|
| -
|
| - // Keep only those properties which have been added or changed in the proto
|
| - // during the update.
|
| - std::set<drive::Property, PropertyCompare> synced_properties(
|
| - local_state->entry.new_properties().begin(),
|
| - local_state->entry.new_properties().end());
|
| -
|
| - google::protobuf::RepeatedPtrField<drive::Property> not_synced_properties;
|
| - for (const auto& property : entry.new_properties()) {
|
| - if (!synced_properties.count(property)) {
|
| - Property* const not_synced_property = not_synced_properties.Add();
|
| - not_synced_property->CopyFrom(property);
|
| - }
|
| - }
|
| - entry.mutable_new_properties()->Swap(¬_synced_properties);
|
| -
|
| - error = metadata->RefreshEntry(entry);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - base::FilePath entry_path;
|
| - error = metadata->GetFilePath(local_state->entry.local_id(), &entry_path);
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - changed_files->Update(entry_path, entry,
|
| - FileChange::CHANGE_TYPE_ADD_OR_UPDATE);
|
| -
|
| - // Clear dirty bit unless the file has been edited during update.
|
| - if (entry.file_specific_info().cache_state().is_dirty() &&
|
| - entry.file_specific_info().cache_state().md5() ==
|
| - entry.file_specific_info().md5()) {
|
| - error = cache->ClearDirty(local_state->entry.local_id());
|
| - if (error != FILE_ERROR_OK)
|
| - return error;
|
| - }
|
| - return FILE_ERROR_OK;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -EntryUpdatePerformer::EntryUpdatePerformer(
|
| - base::SequencedTaskRunner* blocking_task_runner,
|
| - file_system::OperationDelegate* delegate,
|
| - JobScheduler* scheduler,
|
| - ResourceMetadata* metadata,
|
| - FileCache* cache,
|
| - LoaderController* loader_controller)
|
| - : blocking_task_runner_(blocking_task_runner),
|
| - delegate_(delegate),
|
| - scheduler_(scheduler),
|
| - metadata_(metadata),
|
| - cache_(cache),
|
| - loader_controller_(loader_controller),
|
| - remove_performer_(new RemovePerformer(blocking_task_runner,
|
| - delegate,
|
| - scheduler,
|
| - metadata)),
|
| - entry_revert_performer_(new EntryRevertPerformer(blocking_task_runner,
|
| - delegate,
|
| - scheduler,
|
| - metadata)),
|
| - weak_ptr_factory_(this) {
|
| -}
|
| -
|
| -EntryUpdatePerformer::~EntryUpdatePerformer() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -}
|
| -
|
| -void EntryUpdatePerformer::UpdateEntry(const std::string& local_id,
|
| - const ClientContext& context,
|
| - const FileOperationCallback& callback) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - DCHECK(!callback.is_null());
|
| -
|
| - scoped_ptr<LocalState> local_state(new LocalState);
|
| - LocalState* const local_state_ptr = local_state.get();
|
| - base::PostTaskAndReplyWithResult(
|
| - blocking_task_runner_.get(),
|
| - FROM_HERE,
|
| - base::Bind(&PrepareUpdate, metadata_, cache_, local_id, local_state_ptr),
|
| - base::Bind(&EntryUpdatePerformer::UpdateEntryAfterPrepare,
|
| - weak_ptr_factory_.GetWeakPtr(), context, callback,
|
| - base::Passed(&local_state)));
|
| -}
|
| -
|
| -void EntryUpdatePerformer::UpdateEntryAfterPrepare(
|
| - const ClientContext& context,
|
| - const FileOperationCallback& callback,
|
| - scoped_ptr<LocalState> local_state,
|
| - FileError error) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - DCHECK(!callback.is_null());
|
| -
|
| - if (error != FILE_ERROR_OK) {
|
| - callback.Run(error);
|
| - return;
|
| - }
|
| -
|
| - // Trashed entry should be removed.
|
| - if (local_state->entry.parent_local_id() == util::kDriveTrashDirLocalId) {
|
| - remove_performer_->Remove(local_state->entry.local_id(), context, callback);
|
| - return;
|
| - }
|
| -
|
| - // Parent was locally created and needs update. Just return for now.
|
| - // This entry should be updated again after the parent update completes.
|
| - if (local_state->parent_entry.resource_id().empty() &&
|
| - local_state->parent_entry.metadata_edit_state() != ResourceEntry::CLEAN) {
|
| - callback.Run(FILE_ERROR_OK);
|
| - return;
|
| - }
|
| -
|
| - base::Time last_modified = base::Time::FromInternalValue(
|
| - local_state->entry.file_info().last_modified());
|
| - base::Time last_accessed = base::Time::FromInternalValue(
|
| - local_state->entry.file_info().last_accessed());
|
| -
|
| - // Compose a list of new properties from the proto.
|
| - google_apis::drive::Properties properties;
|
| - for (const auto& proto_property : local_state->entry.new_properties()) {
|
| - google_apis::drive::Property property;
|
| - switch (proto_property.visibility()) {
|
| - case Property_Visibility_PRIVATE:
|
| - property.set_visibility(
|
| - google_apis::drive::Property::VISIBILITY_PRIVATE);
|
| - break;
|
| - case Property_Visibility_PUBLIC:
|
| - property.set_visibility(
|
| - google_apis::drive::Property::VISIBILITY_PUBLIC);
|
| - break;
|
| - }
|
| - property.set_key(proto_property.key());
|
| - property.set_value(proto_property.value());
|
| - properties.push_back(property);
|
| - }
|
| -
|
| - // Perform content update.
|
| - if (local_state->should_content_update) {
|
| - if (local_state->entry.resource_id().empty()) {
|
| - // Not locking the loader intentionally here to avoid making the UI
|
| - // unresponsive while uploading large files.
|
| - // FinishUpdate() is responsible to resolve conflicts caused by this.
|
| - scoped_ptr<base::ScopedClosureRunner> null_loader_lock;
|
| -
|
| - UploadNewFileOptions options;
|
| - options.modified_date = last_modified;
|
| - options.last_viewed_by_me_date = last_accessed;
|
| - options.properties = properties;
|
| - LocalState* const local_state_ptr = local_state.get();
|
| - scheduler_->UploadNewFile(
|
| - local_state_ptr->parent_entry.resource_id(),
|
| - local_state_ptr->cache_file_size, local_state_ptr->drive_file_path,
|
| - local_state_ptr->cache_file_path, local_state_ptr->entry.title(),
|
| - local_state_ptr->entry.file_specific_info().content_mime_type(),
|
| - options, context,
|
| - base::Bind(&EntryUpdatePerformer::UpdateEntryAfterUpdateResource,
|
| - weak_ptr_factory_.GetWeakPtr(), context, callback,
|
| - base::Passed(&local_state),
|
| - base::Passed(&null_loader_lock)));
|
| - } else {
|
| - UploadExistingFileOptions options;
|
| - options.title = local_state->entry.title();
|
| - options.parent_resource_id = local_state->parent_entry.resource_id();
|
| - options.modified_date = last_modified;
|
| - options.last_viewed_by_me_date = last_accessed;
|
| - options.properties = properties;
|
| - LocalState* const local_state_ptr = local_state.get();
|
| - scheduler_->UploadExistingFile(
|
| - local_state_ptr->entry.resource_id(),
|
| - local_state_ptr->cache_file_size, local_state_ptr->drive_file_path,
|
| - local_state_ptr->cache_file_path,
|
| - local_state_ptr->entry.file_specific_info().content_mime_type(),
|
| - options, context,
|
| - base::Bind(&EntryUpdatePerformer::UpdateEntryAfterUpdateResource,
|
| - weak_ptr_factory_.GetWeakPtr(), context, callback,
|
| - base::Passed(&local_state),
|
| - base::Passed(scoped_ptr<base::ScopedClosureRunner>())));
|
| - }
|
| - return;
|
| - }
|
| -
|
| - // Create directory.
|
| - if (local_state->entry.file_info().is_directory() &&
|
| - local_state->entry.resource_id().empty()) {
|
| - // Lock the loader to avoid race conditions.
|
| - scoped_ptr<base::ScopedClosureRunner> loader_lock =
|
| - loader_controller_->GetLock();
|
| -
|
| - AddNewDirectoryOptions options;
|
| - options.modified_date = last_modified;
|
| - options.last_viewed_by_me_date = last_accessed;
|
| - options.properties = properties;
|
| - LocalState* const local_state_ptr = local_state.get();
|
| - scheduler_->AddNewDirectory(
|
| - local_state_ptr->parent_entry.resource_id(),
|
| - local_state_ptr->entry.title(), options, context,
|
| - base::Bind(&EntryUpdatePerformer::UpdateEntryAfterUpdateResource,
|
| - weak_ptr_factory_.GetWeakPtr(), context, callback,
|
| - base::Passed(&local_state), base::Passed(&loader_lock)));
|
| - return;
|
| - }
|
| -
|
| - // No need to perform update.
|
| - if (local_state->entry.metadata_edit_state() == ResourceEntry::CLEAN ||
|
| - local_state->entry.resource_id().empty()) {
|
| - callback.Run(FILE_ERROR_OK);
|
| - return;
|
| - }
|
| -
|
| - // Perform metadata update.
|
| - LocalState* const local_state_ptr = local_state.get();
|
| - scheduler_->UpdateResource(
|
| - local_state_ptr->entry.resource_id(),
|
| - local_state_ptr->parent_entry.resource_id(),
|
| - local_state_ptr->entry.title(), last_modified, last_accessed, properties,
|
| - context,
|
| - base::Bind(&EntryUpdatePerformer::UpdateEntryAfterUpdateResource,
|
| - weak_ptr_factory_.GetWeakPtr(), context, callback,
|
| - base::Passed(&local_state),
|
| - base::Passed(scoped_ptr<base::ScopedClosureRunner>())));
|
| -}
|
| -
|
| -void EntryUpdatePerformer::UpdateEntryAfterUpdateResource(
|
| - const ClientContext& context,
|
| - const FileOperationCallback& callback,
|
| - scoped_ptr<LocalState> local_state,
|
| - scoped_ptr<base::ScopedClosureRunner> loader_lock,
|
| - google_apis::DriveApiErrorCode status,
|
| - scoped_ptr<google_apis::FileResource> entry) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - DCHECK(!callback.is_null());
|
| -
|
| - if (status == google_apis::HTTP_FORBIDDEN) {
|
| - // Editing this entry is not allowed, revert local changes.
|
| - entry_revert_performer_->RevertEntry(local_state->entry.local_id(), context,
|
| - callback);
|
| - return;
|
| - }
|
| -
|
| - FileError error = GDataToFileError(status);
|
| - if (error != FILE_ERROR_OK) {
|
| - callback.Run(error);
|
| - return;
|
| - }
|
| -
|
| - FileChange* changed_files = new FileChange;
|
| - base::PostTaskAndReplyWithResult(
|
| - blocking_task_runner_.get(), FROM_HERE,
|
| - base::Bind(&FinishUpdate, metadata_, cache_, base::Passed(&local_state),
|
| - base::Passed(&entry), changed_files),
|
| - base::Bind(&EntryUpdatePerformer::UpdateEntryAfterFinish,
|
| - weak_ptr_factory_.GetWeakPtr(), callback,
|
| - base::Owned(changed_files)));
|
| -}
|
| -
|
| -void EntryUpdatePerformer::UpdateEntryAfterFinish(
|
| - const FileOperationCallback& callback,
|
| - const FileChange* changed_files,
|
| - FileError error) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - DCHECK(!callback.is_null());
|
| -
|
| - delegate_->OnFileChangedByOperation(*changed_files);
|
| - callback.Run(error);
|
| -}
|
| -
|
| -} // namespace internal
|
| -} // namespace drive
|
|
|