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

Unified Diff: chrome/browser/chromeos/drive/change_list_loader.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_loader.cc
diff --git a/chrome/browser/chromeos/drive/change_list_loader.cc b/chrome/browser/chromeos/drive/change_list_loader.cc
deleted file mode 100644
index abe0fa4439fbcf304e25015bb258a152faad0006..0000000000000000000000000000000000000000
--- a/chrome/browser/chromeos/drive/change_list_loader.cc
+++ /dev/null
@@ -1,585 +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_loader.h"
-
-#include <set>
-
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/metrics/histogram.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/cancellation_flag.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "chrome/browser/chromeos/drive/change_list_loader_observer.h"
-#include "chrome/browser/chromeos/drive/change_list_processor.h"
-#include "chrome/browser/chromeos/drive/file_system_core_util.h"
-#include "chrome/browser/chromeos/drive/job_scheduler.h"
-#include "chrome/browser/chromeos/drive/resource_metadata.h"
-#include "components/drive/event_logger.h"
-#include "google_apis/drive/drive_api_parser.h"
-#include "url/gurl.h"
-
-namespace drive {
-namespace internal {
-
-typedef base::Callback<void(FileError, ScopedVector<ChangeList>)>
- FeedFetcherCallback;
-
-class ChangeListLoader::FeedFetcher {
- public:
- virtual ~FeedFetcher() {}
- virtual void Run(const FeedFetcherCallback& callback) = 0;
-};
-
-namespace {
-
-// Fetches all the (currently available) resource entries from the server.
-class FullFeedFetcher : public ChangeListLoader::FeedFetcher {
- public:
- explicit FullFeedFetcher(JobScheduler* scheduler)
- : scheduler_(scheduler),
- weak_ptr_factory_(this) {
- }
-
- ~FullFeedFetcher() override {}
-
- void Run(const FeedFetcherCallback& callback) override {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- // Remember the time stamp for usage stats.
- start_time_ = base::TimeTicks::Now();
-
- // This is full resource list fetch.
- scheduler_->GetAllFileList(
- base::Bind(&FullFeedFetcher::OnFileListFetched,
- weak_ptr_factory_.GetWeakPtr(), callback));
- }
-
- private:
- void OnFileListFetched(const FeedFetcherCallback& callback,
- google_apis::DriveApiErrorCode status,
- scoped_ptr<google_apis::FileList> file_list) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- FileError error = GDataToFileError(status);
- if (error != FILE_ERROR_OK) {
- callback.Run(error, ScopedVector<ChangeList>());
- return;
- }
-
- DCHECK(file_list);
- change_lists_.push_back(new ChangeList(*file_list));
-
- if (!file_list->next_link().is_empty()) {
- // There is the remaining result so fetch it.
- scheduler_->GetRemainingFileList(
- file_list->next_link(),
- base::Bind(&FullFeedFetcher::OnFileListFetched,
- weak_ptr_factory_.GetWeakPtr(), callback));
- return;
- }
-
- UMA_HISTOGRAM_LONG_TIMES("Drive.FullFeedLoadTime",
- base::TimeTicks::Now() - start_time_);
-
- // Note: The fetcher is managed by ChangeListLoader, and the instance
- // will be deleted in the callback. Do not touch the fields after this
- // invocation.
- callback.Run(FILE_ERROR_OK, change_lists_.Pass());
- }
-
- JobScheduler* scheduler_;
- ScopedVector<ChangeList> change_lists_;
- base::TimeTicks start_time_;
- base::ThreadChecker thread_checker_;
- base::WeakPtrFactory<FullFeedFetcher> weak_ptr_factory_;
- DISALLOW_COPY_AND_ASSIGN(FullFeedFetcher);
-};
-
-// Fetches the delta changes since |start_change_id|.
-class DeltaFeedFetcher : public ChangeListLoader::FeedFetcher {
- public:
- DeltaFeedFetcher(JobScheduler* scheduler, int64 start_change_id)
- : scheduler_(scheduler),
- start_change_id_(start_change_id),
- weak_ptr_factory_(this) {
- }
-
- ~DeltaFeedFetcher() override {}
-
- void Run(const FeedFetcherCallback& callback) override {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- scheduler_->GetChangeList(
- start_change_id_,
- base::Bind(&DeltaFeedFetcher::OnChangeListFetched,
- weak_ptr_factory_.GetWeakPtr(), callback));
- }
-
- private:
- void OnChangeListFetched(const FeedFetcherCallback& callback,
- google_apis::DriveApiErrorCode status,
- scoped_ptr<google_apis::ChangeList> change_list) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- FileError error = GDataToFileError(status);
- if (error != FILE_ERROR_OK) {
- callback.Run(error, ScopedVector<ChangeList>());
- return;
- }
-
- DCHECK(change_list);
- change_lists_.push_back(new ChangeList(*change_list));
-
- if (!change_list->next_link().is_empty()) {
- // There is the remaining result so fetch it.
- scheduler_->GetRemainingChangeList(
- change_list->next_link(),
- base::Bind(&DeltaFeedFetcher::OnChangeListFetched,
- weak_ptr_factory_.GetWeakPtr(), callback));
- return;
- }
-
- // Note: The fetcher is managed by ChangeListLoader, and the instance
- // will be deleted in the callback. Do not touch the fields after this
- // invocation.
- callback.Run(FILE_ERROR_OK, change_lists_.Pass());
- }
-
- JobScheduler* scheduler_;
- int64 start_change_id_;
- ScopedVector<ChangeList> change_lists_;
- base::ThreadChecker thread_checker_;
- base::WeakPtrFactory<DeltaFeedFetcher> weak_ptr_factory_;
- DISALLOW_COPY_AND_ASSIGN(DeltaFeedFetcher);
-};
-
-} // namespace
-
-LoaderController::LoaderController()
- : lock_count_(0),
- weak_ptr_factory_(this) {
-}
-
-LoaderController::~LoaderController() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-scoped_ptr<base::ScopedClosureRunner> LoaderController::GetLock() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- ++lock_count_;
- return make_scoped_ptr(new base::ScopedClosureRunner(
- base::Bind(&LoaderController::Unlock,
- weak_ptr_factory_.GetWeakPtr())));
-}
-
-void LoaderController::ScheduleRun(const base::Closure& task) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!task.is_null());
-
- if (lock_count_ > 0) {
- pending_tasks_.push_back(task);
- } else {
- task.Run();
- }
-}
-
-void LoaderController::Unlock() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK_LT(0, lock_count_);
-
- if (--lock_count_ > 0)
- return;
-
- std::vector<base::Closure> tasks;
- tasks.swap(pending_tasks_);
- for (size_t i = 0; i < tasks.size(); ++i)
- tasks[i].Run();
-}
-
-AboutResourceLoader::AboutResourceLoader(JobScheduler* scheduler)
- : scheduler_(scheduler),
- current_update_task_id_(-1),
- weak_ptr_factory_(this) {
-}
-
-AboutResourceLoader::~AboutResourceLoader() {}
-
-void AboutResourceLoader::GetAboutResource(
- const google_apis::AboutResourceCallback& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- // If the latest UpdateAboutResource task is still running. Wait for it,
- if (pending_callbacks_.count(current_update_task_id_)) {
- pending_callbacks_[current_update_task_id_].push_back(callback);
- return;
- }
-
- if (cached_about_resource_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(
- callback,
- google_apis::HTTP_NO_CONTENT,
- base::Passed(scoped_ptr<google_apis::AboutResource>(
- new google_apis::AboutResource(*cached_about_resource_)))));
- } else {
- UpdateAboutResource(callback);
- }
-}
-
-void AboutResourceLoader::UpdateAboutResource(
- const google_apis::AboutResourceCallback& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- ++current_update_task_id_;
- pending_callbacks_[current_update_task_id_].push_back(callback);
-
- scheduler_->GetAboutResource(
- base::Bind(&AboutResourceLoader::UpdateAboutResourceAfterGetAbout,
- weak_ptr_factory_.GetWeakPtr(),
- current_update_task_id_));
-}
-
-void AboutResourceLoader::UpdateAboutResourceAfterGetAbout(
- int task_id,
- google_apis::DriveApiErrorCode status,
- scoped_ptr<google_apis::AboutResource> about_resource) {
- DCHECK(thread_checker_.CalledOnValidThread());
- FileError error = GDataToFileError(status);
-
- const std::vector<google_apis::AboutResourceCallback> callbacks =
- pending_callbacks_[task_id];
- pending_callbacks_.erase(task_id);
-
- if (error != FILE_ERROR_OK) {
- for (size_t i = 0; i < callbacks.size(); ++i)
- callbacks[i].Run(status, scoped_ptr<google_apis::AboutResource>());
- return;
- }
-
- // Updates the cache when the resource is successfully obtained.
- if (cached_about_resource_ &&
- cached_about_resource_->largest_change_id() >
- about_resource->largest_change_id()) {
- LOG(WARNING) << "Local cached about resource is fresher than server, "
- << "local = " << cached_about_resource_->largest_change_id()
- << ", server = " << about_resource->largest_change_id();
- }
- cached_about_resource_.reset(new google_apis::AboutResource(*about_resource));
-
- for (size_t i = 0; i < callbacks.size(); ++i) {
- callbacks[i].Run(
- status,
- make_scoped_ptr(new google_apis::AboutResource(*about_resource)));
- }
-}
-
-ChangeListLoader::ChangeListLoader(
- EventLogger* logger,
- base::SequencedTaskRunner* blocking_task_runner,
- ResourceMetadata* resource_metadata,
- JobScheduler* scheduler,
- AboutResourceLoader* about_resource_loader,
- LoaderController* loader_controller)
- : logger_(logger),
- blocking_task_runner_(blocking_task_runner),
- in_shutdown_(new base::CancellationFlag),
- resource_metadata_(resource_metadata),
- scheduler_(scheduler),
- about_resource_loader_(about_resource_loader),
- loader_controller_(loader_controller),
- loaded_(false),
- weak_ptr_factory_(this) {
-}
-
-ChangeListLoader::~ChangeListLoader() {
- in_shutdown_->Set();
- // Delete |in_shutdown_| with the blocking task runner so that it gets deleted
- // after all active ChangeListProcessors.
- blocking_task_runner_->DeleteSoon(FROM_HERE, in_shutdown_.release());
-}
-
-bool ChangeListLoader::IsRefreshing() const {
- // Callback for change list loading is stored in pending_load_callback_.
- // It is non-empty if and only if there is an in-flight loading operation.
- return !pending_load_callback_.empty();
-}
-
-void ChangeListLoader::AddObserver(ChangeListLoaderObserver* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observers_.AddObserver(observer);
-}
-
-void ChangeListLoader::RemoveObserver(ChangeListLoaderObserver* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observers_.RemoveObserver(observer);
-}
-
-void ChangeListLoader::CheckForUpdates(const FileOperationCallback& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- // We only start to check for updates iff the load is done.
- // I.e., we ignore checking updates if not loaded to avoid starting the
- // load without user's explicit interaction (such as opening Drive).
- if (!loaded_ && !IsRefreshing())
- return;
-
- // For each CheckForUpdates() request, always refresh the changestamp info.
- about_resource_loader_->UpdateAboutResource(
- base::Bind(&ChangeListLoader::OnAboutResourceUpdated,
- weak_ptr_factory_.GetWeakPtr()));
-
- if (IsRefreshing()) {
- // There is in-flight loading. So keep the callback here, and check for
- // updates when the in-flight loading is completed.
- pending_update_check_callback_ = callback;
- return;
- }
-
- DCHECK(loaded_);
- logger_->Log(logging::LOG_INFO, "Checking for updates");
- Load(callback);
-}
-
-void ChangeListLoader::LoadIfNeeded(const FileOperationCallback& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- // If the metadata is not yet loaded, start loading.
- if (!loaded_ && !IsRefreshing())
- Load(callback);
-}
-
-void ChangeListLoader::Load(const FileOperationCallback& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- // Check if this is the first time this ChangeListLoader do loading.
- // Note: IsRefreshing() depends on pending_load_callback_ so check in advance.
- const bool is_initial_load = (!loaded_ && !IsRefreshing());
-
- // Register the callback function to be called when it is loaded.
- pending_load_callback_.push_back(callback);
-
- // If loading task is already running, do nothing.
- if (pending_load_callback_.size() > 1)
- return;
-
- // Check the current status of local metadata, and start loading if needed.
- int64* local_changestamp = new int64(0);
- base::PostTaskAndReplyWithResult(
- blocking_task_runner_.get(),
- FROM_HERE,
- base::Bind(&ResourceMetadata::GetLargestChangestamp,
- base::Unretained(resource_metadata_),
- local_changestamp),
- base::Bind(&ChangeListLoader::LoadAfterGetLargestChangestamp,
- weak_ptr_factory_.GetWeakPtr(),
- is_initial_load,
- base::Owned(local_changestamp)));
-}
-
-void ChangeListLoader::LoadAfterGetLargestChangestamp(
- bool is_initial_load,
- const int64* local_changestamp,
- FileError error) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (error != FILE_ERROR_OK) {
- OnChangeListLoadComplete(error);
- return;
- }
-
- if (is_initial_load && *local_changestamp > 0) {
- // The local data is usable. Flush callbacks to tell loading was successful.
- OnChangeListLoadComplete(FILE_ERROR_OK);
-
- // Continues to load from server in background.
- // Put dummy callbacks to indicate that fetching is still continuing.
- pending_load_callback_.push_back(
- base::Bind(&util::EmptyFileOperationCallback));
- }
-
- about_resource_loader_->GetAboutResource(
- base::Bind(&ChangeListLoader::LoadAfterGetAboutResource,
- weak_ptr_factory_.GetWeakPtr(),
- *local_changestamp));
-}
-
-void ChangeListLoader::LoadAfterGetAboutResource(
- int64 local_changestamp,
- google_apis::DriveApiErrorCode status,
- scoped_ptr<google_apis::AboutResource> about_resource) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- FileError error = GDataToFileError(status);
- if (error != FILE_ERROR_OK) {
- OnChangeListLoadComplete(error);
- return;
- }
-
- DCHECK(about_resource);
-
- int64 remote_changestamp = about_resource->largest_change_id();
- int64 start_changestamp = local_changestamp > 0 ? local_changestamp + 1 : 0;
- if (local_changestamp >= remote_changestamp) {
- if (local_changestamp > remote_changestamp) {
- LOG(WARNING) << "Local resource metadata is fresher than server, "
- << "local = " << local_changestamp
- << ", server = " << remote_changestamp;
- }
-
- // No changes detected, tell the client that the loading was successful.
- OnChangeListLoadComplete(FILE_ERROR_OK);
- } else {
- // Start loading the change list.
- LoadChangeListFromServer(start_changestamp);
- }
-}
-
-void ChangeListLoader::OnChangeListLoadComplete(FileError error) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!loaded_ && error == FILE_ERROR_OK) {
- loaded_ = true;
- FOR_EACH_OBSERVER(ChangeListLoaderObserver,
- observers_,
- OnInitialLoadComplete());
- }
-
- for (size_t i = 0; i < pending_load_callback_.size(); ++i) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(pending_load_callback_[i], error));
- }
- pending_load_callback_.clear();
-
- // If there is pending update check, try to load the change from the server
- // again, because there may exist an update during the completed loading.
- if (!pending_update_check_callback_.is_null()) {
- Load(base::ResetAndReturn(&pending_update_check_callback_));
- }
-}
-
-void ChangeListLoader::OnAboutResourceUpdated(
- google_apis::DriveApiErrorCode error,
- scoped_ptr<google_apis::AboutResource> resource) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (drive::GDataToFileError(error) != drive::FILE_ERROR_OK) {
- logger_->Log(logging::LOG_ERROR,
- "Failed to update the about resource: %s",
- google_apis::DriveApiErrorCodeToString(error).c_str());
- return;
- }
- logger_->Log(logging::LOG_INFO,
- "About resource updated to: %s",
- base::Int64ToString(resource->largest_change_id()).c_str());
-}
-
-void ChangeListLoader::LoadChangeListFromServer(int64 start_changestamp) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!change_feed_fetcher_);
- DCHECK(about_resource_loader_->cached_about_resource());
-
- bool is_delta_update = start_changestamp != 0;
-
- // Set up feed fetcher.
- if (is_delta_update) {
- change_feed_fetcher_.reset(
- new DeltaFeedFetcher(scheduler_, start_changestamp));
- } else {
- change_feed_fetcher_.reset(new FullFeedFetcher(scheduler_));
- }
-
- // Make a copy of cached_about_resource_ to remember at which changestamp we
- // are fetching change list.
- change_feed_fetcher_->Run(
- base::Bind(&ChangeListLoader::LoadChangeListFromServerAfterLoadChangeList,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(make_scoped_ptr(new google_apis::AboutResource(
- *about_resource_loader_->cached_about_resource()))),
- is_delta_update));
-}
-
-void ChangeListLoader::LoadChangeListFromServerAfterLoadChangeList(
- scoped_ptr<google_apis::AboutResource> about_resource,
- bool is_delta_update,
- FileError error,
- ScopedVector<ChangeList> change_lists) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(about_resource);
-
- // Delete the fetcher first.
- change_feed_fetcher_.reset();
-
- if (error != FILE_ERROR_OK) {
- OnChangeListLoadComplete(error);
- return;
- }
-
- ChangeListProcessor* change_list_processor =
- new ChangeListProcessor(resource_metadata_, in_shutdown_.get());
- // Don't send directory content change notification while performing
- // the initial content retrieval.
- const bool should_notify_changed_directories = is_delta_update;
-
- logger_->Log(logging::LOG_INFO,
- "Apply change lists (is delta: %d)",
- is_delta_update);
- loader_controller_->ScheduleRun(base::Bind(
- base::IgnoreResult(
- &base::PostTaskAndReplyWithResult<FileError, FileError>),
- blocking_task_runner_,
- FROM_HERE,
- base::Bind(&ChangeListProcessor::Apply,
- base::Unretained(change_list_processor),
- base::Passed(&about_resource),
- base::Passed(&change_lists),
- is_delta_update),
- base::Bind(&ChangeListLoader::LoadChangeListFromServerAfterUpdate,
- weak_ptr_factory_.GetWeakPtr(),
- base::Owned(change_list_processor),
- should_notify_changed_directories,
- base::Time::Now())));
-}
-
-void ChangeListLoader::LoadChangeListFromServerAfterUpdate(
- ChangeListProcessor* change_list_processor,
- bool should_notify_changed_directories,
- const base::Time& start_time,
- FileError error) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- const base::TimeDelta elapsed = base::Time::Now() - start_time;
- logger_->Log(logging::LOG_INFO,
- "Change lists applied (elapsed time: %sms)",
- base::Int64ToString(elapsed.InMilliseconds()).c_str());
-
- if (should_notify_changed_directories) {
- FOR_EACH_OBSERVER(ChangeListLoaderObserver,
- observers_,
- OnFileChanged(change_list_processor->changed_files()));
- }
-
- OnChangeListLoadComplete(error);
-
- FOR_EACH_OBSERVER(ChangeListLoaderObserver,
- observers_,
- OnLoadFromServerComplete());
-}
-
-} // namespace internal
-} // namespace drive

Powered by Google App Engine
This is Rietveld 408576698