Index: chrome/browser/chromeos/drive/directory_loader.cc |
diff --git a/chrome/browser/chromeos/drive/directory_loader.cc b/chrome/browser/chromeos/drive/directory_loader.cc |
deleted file mode 100644 |
index 5f2e4c2d40fa37b78d332dafcaf226070647bd0b..0000000000000000000000000000000000000000 |
--- a/chrome/browser/chromeos/drive/directory_loader.cc |
+++ /dev/null |
@@ -1,571 +0,0 @@ |
-// Copyright 2014 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/directory_loader.h" |
- |
-#include "base/callback.h" |
-#include "base/callback_helpers.h" |
-#include "base/metrics/histogram.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/time/time.h" |
-#include "components/drive/change_list_loader.h" |
-#include "components/drive/change_list_loader_observer.h" |
-#include "components/drive/change_list_processor.h" |
-#include "components/drive/event_logger.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" |
-#include "url/gurl.h" |
- |
-namespace drive { |
-namespace internal { |
- |
-namespace { |
- |
-// Minimum changestamp gap required to start loading directory. |
-const int kMinimumChangestampGap = 50; |
- |
-FileError CheckLocalState(ResourceMetadata* resource_metadata, |
- const google_apis::AboutResource& about_resource, |
- const std::string& local_id, |
- ResourceEntry* entry, |
- int64* local_changestamp) { |
- // Fill My Drive resource ID. |
- ResourceEntry mydrive; |
- FileError error = resource_metadata->GetResourceEntryByPath( |
- util::GetDriveMyDriveRootPath(), &mydrive); |
- if (error != FILE_ERROR_OK) |
- return error; |
- |
- if (mydrive.resource_id().empty()) { |
- mydrive.set_resource_id(about_resource.root_folder_id()); |
- error = resource_metadata->RefreshEntry(mydrive); |
- if (error != FILE_ERROR_OK) |
- return error; |
- } |
- |
- // Get entry. |
- error = resource_metadata->GetResourceEntryById(local_id, entry); |
- if (error != FILE_ERROR_OK) |
- return error; |
- |
- // Get the local changestamp. |
- return resource_metadata->GetLargestChangestamp(local_changestamp); |
-} |
- |
-FileError UpdateChangestamp(ResourceMetadata* resource_metadata, |
- const DirectoryFetchInfo& directory_fetch_info, |
- base::FilePath* directory_path) { |
- // Update the directory changestamp. |
- 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; |
- |
- directory.mutable_directory_specific_info()->set_changestamp( |
- directory_fetch_info.changestamp()); |
- error = resource_metadata->RefreshEntry(directory); |
- if (error != FILE_ERROR_OK) |
- return error; |
- |
- // Get the directory path. |
- return resource_metadata->GetFilePath(directory_fetch_info.local_id(), |
- directory_path); |
-} |
- |
-} // namespace |
- |
-struct DirectoryLoader::ReadDirectoryCallbackState { |
- ReadDirectoryEntriesCallback entries_callback; |
- FileOperationCallback completion_callback; |
- std::set<std::string> sent_entry_names; |
-}; |
- |
-// Fetches the resource entries in the directory with |directory_resource_id|. |
-class DirectoryLoader::FeedFetcher { |
- public: |
- FeedFetcher(DirectoryLoader* loader, |
- const DirectoryFetchInfo& directory_fetch_info, |
- const std::string& root_folder_id) |
- : loader_(loader), |
- directory_fetch_info_(directory_fetch_info), |
- root_folder_id_(root_folder_id), |
- weak_ptr_factory_(this) { |
- } |
- |
- ~FeedFetcher() { |
- } |
- |
- void Run(const FileOperationCallback& callback) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(!callback.is_null()); |
- DCHECK(!directory_fetch_info_.resource_id().empty()); |
- |
- // Remember the time stamp for usage stats. |
- start_time_ = base::TimeTicks::Now(); |
- |
- loader_->scheduler_->GetFileListInDirectory( |
- directory_fetch_info_.resource_id(), |
- base::Bind(&FeedFetcher::OnFileListFetched, |
- weak_ptr_factory_.GetWeakPtr(), callback)); |
- } |
- |
- private: |
- void OnFileListFetched(const FileOperationCallback& 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); |
- return; |
- } |
- |
- DCHECK(file_list); |
- scoped_ptr<ChangeList> change_list(new ChangeList(*file_list)); |
- GURL next_url = file_list->next_link(); |
- |
- ResourceEntryVector* entries = new ResourceEntryVector; |
- loader_->loader_controller_->ScheduleRun(base::Bind( |
- base::IgnoreResult( |
- &base::PostTaskAndReplyWithResult<FileError, FileError>), |
- loader_->blocking_task_runner_, |
- FROM_HERE, |
- base::Bind(&ChangeListProcessor::RefreshDirectory, |
- loader_->resource_metadata_, |
- directory_fetch_info_, |
- base::Passed(&change_list), |
- entries), |
- base::Bind(&FeedFetcher::OnDirectoryRefreshed, |
- weak_ptr_factory_.GetWeakPtr(), |
- callback, |
- next_url, |
- base::Owned(entries)))); |
- } |
- |
- void OnDirectoryRefreshed( |
- const FileOperationCallback& callback, |
- const GURL& next_url, |
- const std::vector<ResourceEntry>* refreshed_entries, |
- FileError error) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(!callback.is_null()); |
- |
- if (error != FILE_ERROR_OK) { |
- callback.Run(error); |
- return; |
- } |
- |
- loader_->SendEntries(directory_fetch_info_.local_id(), *refreshed_entries); |
- |
- if (!next_url.is_empty()) { |
- // There is the remaining result so fetch it. |
- loader_->scheduler_->GetRemainingFileList( |
- next_url, |
- base::Bind(&FeedFetcher::OnFileListFetched, |
- weak_ptr_factory_.GetWeakPtr(), callback)); |
- return; |
- } |
- |
- UMA_HISTOGRAM_TIMES("Drive.DirectoryFeedLoadTime", |
- base::TimeTicks::Now() - start_time_); |
- |
- // Note: The fetcher is managed by DirectoryLoader, and the instance |
- // will be deleted in the callback. Do not touch the fields after this |
- // invocation. |
- callback.Run(FILE_ERROR_OK); |
- } |
- |
- DirectoryLoader* loader_; |
- DirectoryFetchInfo directory_fetch_info_; |
- std::string root_folder_id_; |
- base::TimeTicks start_time_; |
- base::ThreadChecker thread_checker_; |
- base::WeakPtrFactory<FeedFetcher> weak_ptr_factory_; |
- DISALLOW_COPY_AND_ASSIGN(FeedFetcher); |
-}; |
- |
-DirectoryLoader::DirectoryLoader( |
- 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), |
- resource_metadata_(resource_metadata), |
- scheduler_(scheduler), |
- about_resource_loader_(about_resource_loader), |
- loader_controller_(loader_controller), |
- weak_ptr_factory_(this) { |
-} |
- |
-DirectoryLoader::~DirectoryLoader() { |
- STLDeleteElements(&fast_fetch_feed_fetcher_set_); |
-} |
- |
-void DirectoryLoader::AddObserver(ChangeListLoaderObserver* observer) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- observers_.AddObserver(observer); |
-} |
- |
-void DirectoryLoader::RemoveObserver(ChangeListLoaderObserver* observer) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- observers_.RemoveObserver(observer); |
-} |
- |
-void DirectoryLoader::ReadDirectory( |
- const base::FilePath& directory_path, |
- const ReadDirectoryEntriesCallback& entries_callback, |
- const FileOperationCallback& completion_callback) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(!completion_callback.is_null()); |
- |
- ResourceEntry* entry = new ResourceEntry; |
- base::PostTaskAndReplyWithResult( |
- blocking_task_runner_.get(), |
- FROM_HERE, |
- base::Bind(&ResourceMetadata::GetResourceEntryByPath, |
- base::Unretained(resource_metadata_), |
- directory_path, |
- entry), |
- base::Bind(&DirectoryLoader::ReadDirectoryAfterGetEntry, |
- weak_ptr_factory_.GetWeakPtr(), |
- directory_path, |
- entries_callback, |
- completion_callback, |
- true, // should_try_loading_parent |
- base::Owned(entry))); |
-} |
- |
-void DirectoryLoader::ReadDirectoryAfterGetEntry( |
- const base::FilePath& directory_path, |
- const ReadDirectoryEntriesCallback& entries_callback, |
- const FileOperationCallback& completion_callback, |
- bool should_try_loading_parent, |
- const ResourceEntry* entry, |
- FileError error) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(!completion_callback.is_null()); |
- |
- if (error == FILE_ERROR_NOT_FOUND && |
- should_try_loading_parent && |
- util::GetDriveGrandRootPath().IsParent(directory_path)) { |
- // This entry may be found after loading the parent. |
- ReadDirectory(directory_path.DirName(), |
- ReadDirectoryEntriesCallback(), |
- base::Bind(&DirectoryLoader::ReadDirectoryAfterLoadParent, |
- weak_ptr_factory_.GetWeakPtr(), |
- directory_path, |
- entries_callback, |
- completion_callback)); |
- return; |
- } |
- if (error != FILE_ERROR_OK) { |
- completion_callback.Run(error); |
- return; |
- } |
- |
- if (!entry->file_info().is_directory()) { |
- completion_callback.Run(FILE_ERROR_NOT_A_DIRECTORY); |
- return; |
- } |
- |
- DirectoryFetchInfo directory_fetch_info( |
- entry->local_id(), |
- entry->resource_id(), |
- entry->directory_specific_info().changestamp()); |
- |
- // Register the callback function to be called when it is loaded. |
- const std::string& local_id = directory_fetch_info.local_id(); |
- ReadDirectoryCallbackState callback_state; |
- callback_state.entries_callback = entries_callback; |
- callback_state.completion_callback = completion_callback; |
- pending_load_callback_[local_id].push_back(callback_state); |
- |
- // If loading task for |local_id| is already running, do nothing. |
- if (pending_load_callback_[local_id].size() > 1) |
- return; |
- |
- about_resource_loader_->GetAboutResource( |
- base::Bind(&DirectoryLoader::ReadDirectoryAfterGetAboutResource, |
- weak_ptr_factory_.GetWeakPtr(), local_id)); |
-} |
- |
-void DirectoryLoader::ReadDirectoryAfterLoadParent( |
- const base::FilePath& directory_path, |
- const ReadDirectoryEntriesCallback& entries_callback, |
- const FileOperationCallback& completion_callback, |
- FileError error) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(!completion_callback.is_null()); |
- |
- if (error != FILE_ERROR_OK) { |
- completion_callback.Run(error); |
- return; |
- } |
- |
- ResourceEntry* entry = new ResourceEntry; |
- base::PostTaskAndReplyWithResult( |
- blocking_task_runner_.get(), |
- FROM_HERE, |
- base::Bind(&ResourceMetadata::GetResourceEntryByPath, |
- base::Unretained(resource_metadata_), |
- directory_path, |
- entry), |
- base::Bind(&DirectoryLoader::ReadDirectoryAfterGetEntry, |
- weak_ptr_factory_.GetWeakPtr(), |
- directory_path, |
- entries_callback, |
- completion_callback, |
- false, // should_try_loading_parent |
- base::Owned(entry))); |
-} |
- |
-void DirectoryLoader::ReadDirectoryAfterGetAboutResource( |
- const std::string& local_id, |
- google_apis::DriveApiErrorCode status, |
- scoped_ptr<google_apis::AboutResource> about_resource) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- |
- FileError error = GDataToFileError(status); |
- if (error != FILE_ERROR_OK) { |
- OnDirectoryLoadComplete(local_id, error); |
- return; |
- } |
- |
- DCHECK(about_resource); |
- |
- // Check the current status of local metadata, and start loading if needed. |
- google_apis::AboutResource* about_resource_ptr = about_resource.get(); |
- ResourceEntry* entry = new ResourceEntry; |
- int64* local_changestamp = new int64; |
- base::PostTaskAndReplyWithResult( |
- blocking_task_runner_.get(), |
- FROM_HERE, |
- base::Bind(&CheckLocalState, |
- resource_metadata_, |
- *about_resource_ptr, |
- local_id, |
- entry, |
- local_changestamp), |
- base::Bind(&DirectoryLoader::ReadDirectoryAfterCheckLocalState, |
- weak_ptr_factory_.GetWeakPtr(), |
- base::Passed(&about_resource), |
- local_id, |
- base::Owned(entry), |
- base::Owned(local_changestamp))); |
-} |
- |
-void DirectoryLoader::ReadDirectoryAfterCheckLocalState( |
- scoped_ptr<google_apis::AboutResource> about_resource, |
- const std::string& local_id, |
- const ResourceEntry* entry, |
- const int64* local_changestamp, |
- FileError error) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(about_resource); |
- |
- if (error != FILE_ERROR_OK) { |
- OnDirectoryLoadComplete(local_id, error); |
- return; |
- } |
- // This entry does not exist on the server. |
- if (entry->resource_id().empty()) { |
- OnDirectoryLoadComplete(local_id, FILE_ERROR_OK); |
- return; |
- } |
- |
- int64 remote_changestamp = about_resource->largest_change_id(); |
- |
- // Start loading the directory. |
- int64 directory_changestamp = std::max( |
- entry->directory_specific_info().changestamp(), *local_changestamp); |
- |
- DirectoryFetchInfo directory_fetch_info( |
- local_id, entry->resource_id(), remote_changestamp); |
- |
- // If the directory's changestamp is up-to-date or the global changestamp of |
- // the metadata DB is new enough (which means the normal changelist loading |
- // should finish very soon), just schedule to run the callback, as there is no |
- // need to fetch the directory. |
- if (directory_changestamp >= remote_changestamp || |
- *local_changestamp + kMinimumChangestampGap > remote_changestamp) { |
- OnDirectoryLoadComplete(local_id, FILE_ERROR_OK); |
- } else { |
- // Start fetching the directory content, and mark it with the changestamp |
- // |remote_changestamp|. |
- LoadDirectoryFromServer(directory_fetch_info); |
- } |
-} |
- |
-void DirectoryLoader::OnDirectoryLoadComplete(const std::string& local_id, |
- FileError error) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- |
- LoadCallbackMap::iterator it = pending_load_callback_.find(local_id); |
- if (it == pending_load_callback_.end()) |
- return; |
- |
- // No need to read metadata when no one needs entries. |
- bool needs_to_send_entries = false; |
- for (size_t i = 0; i < it->second.size(); ++i) { |
- const ReadDirectoryCallbackState& callback_state = it->second[i]; |
- if (!callback_state.entries_callback.is_null()) |
- needs_to_send_entries = true; |
- } |
- |
- if (!needs_to_send_entries) { |
- OnDirectoryLoadCompleteAfterRead(local_id, NULL, FILE_ERROR_OK); |
- return; |
- } |
- |
- ResourceEntryVector* entries = new ResourceEntryVector; |
- base::PostTaskAndReplyWithResult( |
- blocking_task_runner_.get(), |
- FROM_HERE, |
- base::Bind(&ResourceMetadata::ReadDirectoryById, |
- base::Unretained(resource_metadata_), local_id, entries), |
- base::Bind(&DirectoryLoader::OnDirectoryLoadCompleteAfterRead, |
- weak_ptr_factory_.GetWeakPtr(), |
- local_id, |
- base::Owned(entries))); |
-} |
- |
-void DirectoryLoader::OnDirectoryLoadCompleteAfterRead( |
- const std::string& local_id, |
- const ResourceEntryVector* entries, |
- FileError error) { |
- LoadCallbackMap::iterator it = pending_load_callback_.find(local_id); |
- if (it != pending_load_callback_.end()) { |
- DVLOG(1) << "Running callback for " << local_id; |
- |
- if (error == FILE_ERROR_OK && entries) |
- SendEntries(local_id, *entries); |
- |
- for (size_t i = 0; i < it->second.size(); ++i) { |
- const ReadDirectoryCallbackState& callback_state = it->second[i]; |
- callback_state.completion_callback.Run(error); |
- } |
- pending_load_callback_.erase(it); |
- } |
-} |
- |
-void DirectoryLoader::SendEntries(const std::string& local_id, |
- const ResourceEntryVector& entries) { |
- LoadCallbackMap::iterator it = pending_load_callback_.find(local_id); |
- DCHECK(it != pending_load_callback_.end()); |
- |
- for (size_t i = 0; i < it->second.size(); ++i) { |
- ReadDirectoryCallbackState* callback_state = &it->second[i]; |
- if (callback_state->entries_callback.is_null()) |
- continue; |
- |
- // Filter out entries which were already sent. |
- scoped_ptr<ResourceEntryVector> entries_to_send(new ResourceEntryVector); |
- for (size_t i = 0; i < entries.size(); ++i) { |
- const ResourceEntry& entry = entries[i]; |
- if (!callback_state->sent_entry_names.count(entry.base_name())) { |
- callback_state->sent_entry_names.insert(entry.base_name()); |
- entries_to_send->push_back(entry); |
- } |
- } |
- callback_state->entries_callback.Run(entries_to_send.Pass()); |
- } |
-} |
- |
-void DirectoryLoader::LoadDirectoryFromServer( |
- const DirectoryFetchInfo& directory_fetch_info) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(!directory_fetch_info.empty()); |
- DVLOG(1) << "Start loading directory: " << directory_fetch_info.ToString(); |
- |
- const google_apis::AboutResource* about_resource = |
- about_resource_loader_->cached_about_resource(); |
- DCHECK(about_resource); |
- |
- logger_->Log(logging::LOG_INFO, |
- "Fast-fetch start: %s; Server changestamp: %s", |
- directory_fetch_info.ToString().c_str(), |
- base::Int64ToString( |
- about_resource->largest_change_id()).c_str()); |
- |
- FeedFetcher* fetcher = new FeedFetcher(this, |
- directory_fetch_info, |
- about_resource->root_folder_id()); |
- fast_fetch_feed_fetcher_set_.insert(fetcher); |
- fetcher->Run( |
- base::Bind(&DirectoryLoader::LoadDirectoryFromServerAfterLoad, |
- weak_ptr_factory_.GetWeakPtr(), |
- directory_fetch_info, |
- fetcher)); |
-} |
- |
-void DirectoryLoader::LoadDirectoryFromServerAfterLoad( |
- const DirectoryFetchInfo& directory_fetch_info, |
- FeedFetcher* fetcher, |
- FileError error) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(!directory_fetch_info.empty()); |
- |
- // Delete the fetcher. |
- fast_fetch_feed_fetcher_set_.erase(fetcher); |
- delete fetcher; |
- |
- logger_->Log(logging::LOG_INFO, |
- "Fast-fetch complete: %s => %s", |
- directory_fetch_info.ToString().c_str(), |
- FileErrorToString(error).c_str()); |
- |
- if (error != FILE_ERROR_OK) { |
- LOG(ERROR) << "Failed to load directory: " |
- << directory_fetch_info.local_id() |
- << ": " << FileErrorToString(error); |
- OnDirectoryLoadComplete(directory_fetch_info.local_id(), error); |
- return; |
- } |
- |
- // Update changestamp and get the directory path. |
- base::FilePath* directory_path = new base::FilePath; |
- base::PostTaskAndReplyWithResult( |
- blocking_task_runner_.get(), |
- FROM_HERE, |
- base::Bind(&UpdateChangestamp, |
- resource_metadata_, |
- directory_fetch_info, |
- directory_path), |
- base::Bind( |
- &DirectoryLoader::LoadDirectoryFromServerAfterUpdateChangestamp, |
- weak_ptr_factory_.GetWeakPtr(), |
- directory_fetch_info, |
- base::Owned(directory_path))); |
-} |
- |
-void DirectoryLoader::LoadDirectoryFromServerAfterUpdateChangestamp( |
- const DirectoryFetchInfo& directory_fetch_info, |
- const base::FilePath* directory_path, |
- FileError error) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- |
- DVLOG(1) << "Directory loaded: " << directory_fetch_info.ToString(); |
- OnDirectoryLoadComplete(directory_fetch_info.local_id(), error); |
- |
- // Also notify the observers. |
- if (error == FILE_ERROR_OK && !directory_path->empty()) { |
- FOR_EACH_OBSERVER(ChangeListLoaderObserver, |
- observers_, |
- OnDirectoryReloaded(*directory_path)); |
- } |
-} |
- |
-} // namespace internal |
-} // namespace drive |