Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(719)

Unified Diff: chrome/browser/chromeos/drive/change_list_processor.cc

Issue 1215503010: OBSOLETE: Move (most of) chrome/browser/chromeos/drive into components/drive. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@drive-componentize-service
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/drive/change_list_processor.cc
diff --git a/chrome/browser/chromeos/drive/change_list_processor.cc b/chrome/browser/chromeos/drive/change_list_processor.cc
deleted file mode 100644
index 342efeeeadeee451c537bf20a6ffd520a2536f84..0000000000000000000000000000000000000000
--- a/chrome/browser/chromeos/drive/change_list_processor.cc
+++ /dev/null
@@ -1,502 +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 "chrome/browser/chromeos/drive/change_list_processor.h"
-
-#include "base/metrics/histogram.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/cancellation_flag.h"
-#include "chrome/browser/chromeos/drive/drive.pb.h"
-#include "chrome/browser/chromeos/drive/file_change.h"
-#include "chrome/browser/chromeos/drive/file_system_core_util.h"
-#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
-#include "chrome/browser/chromeos/drive/resource_metadata.h"
-#include "components/drive/drive_api_util.h"
-#include "google_apis/drive/drive_api_parser.h"
-
-namespace drive {
-namespace internal {
-
-namespace {
-
-class ChangeListToEntryMapUMAStats {
- public:
- ChangeListToEntryMapUMAStats()
- : num_regular_files_(0),
- num_hosted_documents_(0),
- num_shared_with_me_entries_(0) {
- }
-
- // Increments number of files.
- void IncrementNumFiles(bool is_hosted_document) {
- is_hosted_document ? num_hosted_documents_++ : num_regular_files_++;
- }
-
- // Increments number of shared-with-me entries.
- void IncrementNumSharedWithMeEntries() {
- num_shared_with_me_entries_++;
- }
-
- // Updates UMA histograms with file counts.
- void UpdateFileCountUmaHistograms() {
- const int num_total_files = num_hosted_documents_ + num_regular_files_;
- UMA_HISTOGRAM_COUNTS("Drive.NumberOfRegularFiles", num_regular_files_);
- UMA_HISTOGRAM_COUNTS("Drive.NumberOfHostedDocuments",
- num_hosted_documents_);
- UMA_HISTOGRAM_COUNTS("Drive.NumberOfTotalFiles", num_total_files);
- UMA_HISTOGRAM_COUNTS("Drive.NumberOfSharedWithMeEntries",
- num_shared_with_me_entries_);
- }
-
- private:
- int num_regular_files_;
- int num_hosted_documents_;
- int num_shared_with_me_entries_;
-};
-
-// Returns true if it's OK to overwrite the local entry with the remote one.
-bool ShouldApplyChange(const ResourceEntry& local_entry,
- const ResourceEntry& remote_entry) {
- if (local_entry.metadata_edit_state() == ResourceEntry::CLEAN)
- return true;
- return base::Time::FromInternalValue(remote_entry.modification_date()) >
- base::Time::FromInternalValue(local_entry.modification_date());
-}
-
-} // namespace
-
-std::string DirectoryFetchInfo::ToString() const {
- return ("local_id: " + local_id_ +
- ", resource_id: " + resource_id_ +
- ", changestamp: " + base::Int64ToString(changestamp_));
-}
-
-ChangeList::ChangeList() {}
-
-ChangeList::ChangeList(const google_apis::ChangeList& change_list)
- : next_url_(change_list.next_link()),
- largest_changestamp_(change_list.largest_change_id()) {
- const ScopedVector<google_apis::ChangeResource>& items = change_list.items();
- entries_.resize(items.size());
- parent_resource_ids_.resize(items.size());
- size_t entries_index = 0;
- for (size_t i = 0; i < items.size(); ++i) {
- if (ConvertChangeResourceToResourceEntry(
- *items[i],
- &entries_[entries_index],
- &parent_resource_ids_[entries_index])) {
- ++entries_index;
- }
- }
- entries_.resize(entries_index);
- parent_resource_ids_.resize(entries_index);
-}
-
-ChangeList::ChangeList(const google_apis::FileList& file_list)
- : next_url_(file_list.next_link()),
- largest_changestamp_(0) {
- const ScopedVector<google_apis::FileResource>& items = file_list.items();
- entries_.resize(items.size());
- parent_resource_ids_.resize(items.size());
- size_t entries_index = 0;
- for (size_t i = 0; i < items.size(); ++i) {
- if (ConvertFileResourceToResourceEntry(
- *items[i],
- &entries_[entries_index],
- &parent_resource_ids_[entries_index])) {
- ++entries_index;
- }
- }
- entries_.resize(entries_index);
- parent_resource_ids_.resize(entries_index);
-}
-
-ChangeList::~ChangeList() {}
-
-ChangeListProcessor::ChangeListProcessor(ResourceMetadata* resource_metadata,
- base::CancellationFlag* in_shutdown)
- : resource_metadata_(resource_metadata),
- in_shutdown_(in_shutdown),
- changed_files_(new FileChange) {
-}
-
-ChangeListProcessor::~ChangeListProcessor() {
-}
-
-FileError ChangeListProcessor::Apply(
- scoped_ptr<google_apis::AboutResource> about_resource,
- ScopedVector<ChangeList> change_lists,
- bool is_delta_update) {
- DCHECK(about_resource);
-
- int64 largest_changestamp = 0;
- if (is_delta_update) {
- if (!change_lists.empty()) {
- // The changestamp appears in the first page of the change list.
- // The changestamp does not appear in the full resource list.
- largest_changestamp = change_lists[0]->largest_changestamp();
- DCHECK_GE(change_lists[0]->largest_changestamp(), 0);
- }
- } else {
- largest_changestamp = about_resource->largest_change_id();
-
- DVLOG(1) << "Root folder ID is " << about_resource->root_folder_id();
- DCHECK(!about_resource->root_folder_id().empty());
- }
-
- // Convert ChangeList to map.
- ChangeListToEntryMapUMAStats uma_stats;
- for (size_t i = 0; i < change_lists.size(); ++i) {
- ChangeList* change_list = change_lists[i];
-
- std::vector<ResourceEntry>* entries = change_list->mutable_entries();
- for (size_t i = 0; i < entries->size(); ++i) {
- ResourceEntry* entry = &(*entries)[i];
-
- // Count the number of files.
- if (!entry->file_info().is_directory()) {
- uma_stats.IncrementNumFiles(
- entry->file_specific_info().is_hosted_document());
- if (entry->shared_with_me())
- uma_stats.IncrementNumSharedWithMeEntries();
- }
- parent_resource_id_map_[entry->resource_id()] =
- change_list->parent_resource_ids()[i];
- entry_map_[entry->resource_id()].Swap(entry);
- LOG_IF(WARNING, !entry->resource_id().empty())
- << "Found duplicated file: " << entry->base_name();
- }
- }
-
- // Add the largest changestamp for directories.
- for (ResourceEntryMap::iterator it = entry_map_.begin();
- it != entry_map_.end(); ++it) {
- if (it->second.file_info().is_directory()) {
- it->second.mutable_directory_specific_info()->set_changestamp(
- largest_changestamp);
- }
- }
-
- FileError error = ApplyEntryMap(largest_changestamp, about_resource.Pass());
- if (error != FILE_ERROR_OK) {
- DLOG(ERROR) << "ApplyEntryMap failed: " << FileErrorToString(error);
- return error;
- }
-
- // Update changestamp.
- error = resource_metadata_->SetLargestChangestamp(largest_changestamp);
- if (error != FILE_ERROR_OK) {
- DLOG(ERROR) << "SetLargestChangeStamp failed: " << FileErrorToString(error);
- return error;
- }
-
- // Shouldn't record histograms when processing delta update.
- if (!is_delta_update)
- uma_stats.UpdateFileCountUmaHistograms();
-
- return FILE_ERROR_OK;
-}
-
-FileError ChangeListProcessor::ApplyEntryMap(
- int64 changestamp,
- scoped_ptr<google_apis::AboutResource> about_resource) {
- DCHECK(about_resource);
-
- // Create the entry for "My Drive" directory with the latest changestamp.
- ResourceEntry root;
- FileError error = resource_metadata_->GetResourceEntryByPath(
- util::GetDriveMyDriveRootPath(), &root);
- if (error != FILE_ERROR_OK) {
- LOG(ERROR) << "Failed to get root entry: " << FileErrorToString(error);
- return error;
- }
-
- root.mutable_directory_specific_info()->set_changestamp(changestamp);
- root.set_resource_id(about_resource->root_folder_id());
- error = resource_metadata_->RefreshEntry(root);
- if (error != FILE_ERROR_OK) {
- LOG(ERROR) << "Failed to update root entry: " << FileErrorToString(error);
- return error;
- }
-
- // Gather the set of changes in the old path.
- // Note that we want to notify the change in both old and new paths (suppose
- // /a/b/c is moved to /x/y/c. We want to notify both "/a/b" and "/x/y".)
- // The old paths must be calculated before we apply any actual changes.
- // The new paths are calculated after each change is applied. It correctly
- // sets the new path because we apply changes in such an order (see below).
- for (ResourceEntryMap::iterator it = entry_map_.begin();
- it != entry_map_.end(); ++it) {
- UpdateChangedDirs(it->second);
- }
-
- // Apply all entries except deleted ones to the metadata.
- std::vector<std::string> deleted_resource_ids;
- while (!entry_map_.empty()) {
- if (in_shutdown_ && in_shutdown_->IsSet())
- return FILE_ERROR_ABORT;
-
- ResourceEntryMap::iterator it = entry_map_.begin();
-
- // Process deleted entries later to avoid deleting moved entries under it.
- if (it->second.deleted()) {
- deleted_resource_ids.push_back(it->first);
- entry_map_.erase(it);
- continue;
- }
-
- // Start from entry_map_.begin() and traverse ancestors using the
- // parent-child relationships in the result (after this apply) tree.
- // Then apply the topmost change first.
- //
- // By doing this, assuming the result tree does not contain any cycles, we
- // can guarantee that no cycle is made during this apply (i.e. no entry gets
- // moved under any of its descendants) because the following conditions are
- // always satisfied in any move:
- // - The new parent entry is not a descendant of the moved entry.
- // - The new parent and its ancestors will no longer move during this apply.
- std::vector<ResourceEntryMap::iterator> entries;
- for (ResourceEntryMap::iterator it = entry_map_.begin();
- it != entry_map_.end();) {
- entries.push_back(it);
-
- DCHECK(parent_resource_id_map_.count(it->first)) << it->first;
- const std::string& parent_resource_id =
- parent_resource_id_map_[it->first];
-
- if (parent_resource_id.empty()) // This entry has no parent.
- break;
-
- ResourceEntryMap::iterator it_parent =
- entry_map_.find(parent_resource_id);
- if (it_parent == entry_map_.end()) {
- // Current entry's parent is already updated or not going to be updated,
- // get the parent from the local tree.
- std::string parent_local_id;
- FileError error = resource_metadata_->GetIdByResourceId(
- parent_resource_id, &parent_local_id);
- if (error != FILE_ERROR_OK) {
- // See crbug.com/326043. In some complicated situations, parent folder
- // for shared entries may be accessible (and hence its resource id is
- // included), but not in the change/file list.
- // In such a case, clear the parent and move it to drive/other.
- if (error == FILE_ERROR_NOT_FOUND) {
- parent_resource_id_map_[it->first] = "";
- } else {
- LOG(ERROR) << "Failed to get local ID: " << parent_resource_id
- << ", error = " << FileErrorToString(error);
- }
- break;
- }
- ResourceEntry parent_entry;
- while (it_parent == entry_map_.end() && !parent_local_id.empty()) {
- error = resource_metadata_->GetResourceEntryById(
- parent_local_id, &parent_entry);
- if (error != FILE_ERROR_OK) {
- LOG(ERROR) << "Failed to get local entry: "
- << FileErrorToString(error);
- break;
- }
- it_parent = entry_map_.find(parent_entry.resource_id());
- parent_local_id = parent_entry.parent_local_id();
- }
- }
- it = it_parent;
- }
-
- // Apply the parent first.
- std::reverse(entries.begin(), entries.end());
- for (size_t i = 0; i < entries.size(); ++i) {
- // Skip root entry in the change list. We don't expect servers to send
- // root entry, but we should better be defensive (see crbug.com/297259).
- ResourceEntryMap::iterator it = entries[i];
- if (it->first != root.resource_id()) {
- FileError error = ApplyEntry(it->second);
- if (error != FILE_ERROR_OK) {
- LOG(ERROR) << "ApplyEntry failed: " << FileErrorToString(error)
- << ", title = " << it->second.title();
- return error;
- }
- }
- entry_map_.erase(it);
- }
- }
-
- // Apply deleted entries.
- for (size_t i = 0; i < deleted_resource_ids.size(); ++i) {
- std::string local_id;
- FileError error = resource_metadata_->GetIdByResourceId(
- deleted_resource_ids[i], &local_id);
- switch (error) {
- case FILE_ERROR_OK:
- error = resource_metadata_->RemoveEntry(local_id);
- break;
- case FILE_ERROR_NOT_FOUND:
- error = FILE_ERROR_OK;
- break;
- default:
- break;
- }
- if (error != FILE_ERROR_OK) {
- LOG(ERROR) << "Failed to delete: " << FileErrorToString(error)
- << ", resource_id = " << deleted_resource_ids[i];
- return error;
- }
- }
-
- return FILE_ERROR_OK;
-}
-
-FileError ChangeListProcessor::ApplyEntry(const ResourceEntry& entry) {
- DCHECK(!entry.deleted());
- DCHECK(parent_resource_id_map_.count(entry.resource_id()));
- const std::string& parent_resource_id =
- parent_resource_id_map_[entry.resource_id()];
-
- ResourceEntry new_entry(entry);
- FileError error = SetParentLocalIdOfEntry(resource_metadata_, &new_entry,
- parent_resource_id);
- if (error != FILE_ERROR_OK)
- return error;
-
- // Lookup the entry.
- std::string local_id;
- error = resource_metadata_->GetIdByResourceId(entry.resource_id(), &local_id);
-
- ResourceEntry existing_entry;
- if (error == FILE_ERROR_OK)
- error = resource_metadata_->GetResourceEntryById(local_id, &existing_entry);
-
- switch (error) {
- case FILE_ERROR_OK:
- if (ShouldApplyChange(existing_entry, new_entry)) {
- // Entry exists and needs to be refreshed.
- new_entry.set_local_id(local_id);
- // Keep the to-be-synced properties of the existing resource entry.
- new_entry.mutable_new_properties()->CopyFrom(
- existing_entry.new_properties());
- error = resource_metadata_->RefreshEntry(new_entry);
- } else {
- if (entry.file_info().is_directory()) {
- // No need to refresh, but update the changestamp.
- new_entry = existing_entry;
- new_entry.mutable_directory_specific_info()->set_changestamp(
- new_entry.directory_specific_info().changestamp());
- error = resource_metadata_->RefreshEntry(new_entry);
- }
- DVLOG(1) << "Change was discarded for: " << entry.resource_id();
- }
- break;
- case FILE_ERROR_NOT_FOUND: { // Adding a new entry.
- std::string local_id;
- error = resource_metadata_->AddEntry(new_entry, &local_id);
- break;
- }
- default:
- return error;
- }
- if (error != FILE_ERROR_OK)
- return error;
-
- UpdateChangedDirs(entry);
- return FILE_ERROR_OK;
-}
-
-// static
-FileError ChangeListProcessor::RefreshDirectory(
- ResourceMetadata* resource_metadata,
- const DirectoryFetchInfo& directory_fetch_info,
- scoped_ptr<ChangeList> change_list,
- std::vector<ResourceEntry>* out_refreshed_entries) {
- DCHECK(!directory_fetch_info.empty());
-
- ResourceEntry directory;
- FileError error = resource_metadata->GetResourceEntryById(
- directory_fetch_info.local_id(), &directory);
- if (error != FILE_ERROR_OK)
- return error;
-
- if (!directory.file_info().is_directory())
- return FILE_ERROR_NOT_A_DIRECTORY;
-
- std::vector<ResourceEntry>* entries = change_list->mutable_entries();
- for (size_t i = 0; i < entries->size(); ++i) {
- ResourceEntry* entry = &(*entries)[i];
- const std::string& parent_resource_id =
- change_list->parent_resource_ids()[i];
-
- // Skip if the parent resource ID does not match. This is needed to
- // handle entries with multiple parents. For such entries, the first
- // parent is picked and other parents are ignored, hence some entries may
- // have a parent resource ID which does not match the target directory's.
- if (parent_resource_id != directory_fetch_info.resource_id()) {
- DVLOG(1) << "Wrong-parent entry rejected: " << entry->resource_id();
- continue;
- }
-
- entry->set_parent_local_id(directory_fetch_info.local_id());
-
- std::string local_id;
- error = resource_metadata->GetIdByResourceId(entry->resource_id(),
- &local_id);
- if (error == FILE_ERROR_OK) {
- entry->set_local_id(local_id);
- error = resource_metadata->RefreshEntry(*entry);
- }
-
- if (error == FILE_ERROR_NOT_FOUND) { // If refreshing fails, try adding.
- entry->clear_local_id();
- error = resource_metadata->AddEntry(*entry, &local_id);
- }
-
- if (error != FILE_ERROR_OK)
- return error;
-
- ResourceEntry result_entry;
- error = resource_metadata->GetResourceEntryById(local_id, &result_entry);
- if (error != FILE_ERROR_OK)
- return error;
- out_refreshed_entries->push_back(result_entry);
- }
- return FILE_ERROR_OK;
-}
-
-// static
-FileError ChangeListProcessor::SetParentLocalIdOfEntry(
- ResourceMetadata* resource_metadata,
- ResourceEntry* entry,
- const std::string& parent_resource_id) {
- std::string parent_local_id;
- if (parent_resource_id.empty()) {
- // Entries without parents should go under "other" directory.
- parent_local_id = util::kDriveOtherDirLocalId;
- } else {
- FileError error = resource_metadata->GetIdByResourceId(
- parent_resource_id, &parent_local_id);
- if (error != FILE_ERROR_OK)
- return error;
- }
- entry->set_parent_local_id(parent_local_id);
- return FILE_ERROR_OK;
-}
-
-void ChangeListProcessor::UpdateChangedDirs(const ResourceEntry& entry) {
- DCHECK(!entry.resource_id().empty());
-
- std::string local_id;
- base::FilePath file_path;
- if (resource_metadata_->GetIdByResourceId(
- entry.resource_id(), &local_id) == FILE_ERROR_OK)
- resource_metadata_->GetFilePath(local_id, &file_path);
-
- if (!file_path.empty()) {
- FileChange::ChangeType type = entry.deleted()
- ? FileChange::CHANGE_TYPE_DELETE
- : FileChange::CHANGE_TYPE_ADD_OR_UPDATE;
- changed_files_->Update(file_path, entry, type);
- }
-}
-
-} // namespace internal
-} // namespace drive

Powered by Google App Engine
This is Rietveld 408576698