From bbf59f290a21cf3ff1656d07904f3c865bc0a438 Mon Sep 17 00:00:00 2001 From: "hashimoto@chromium.org" Date: Mon, 24 Mar 2014 13:55:26 +0000 Subject: [PATCH] drive: Implement Progressive Fast Fetch Send entries to callbacks progressively. Changes for ChangeListProcessor: - RefreshDirectory is no longer responsible to update changestamp, DirectoryLoader will do it instead. Changes for DirectoryLoader: - Add a new method SendEntries() which is responsible to avoid sending the same entry for a callback twice. - FeedFetcher is responsible to run RefreshDirectory() and SendEntries(). BUG=340931 TEST=unit_tests Review URL: https://codereview.chromium.org/194453002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258923 0039d316-1c4b-4281-b951-d872f2087c98 --- .../chromeos/drive/change_list_processor.cc | 77 ++++---- .../browser/chromeos/drive/change_list_processor.h | 7 +- .../drive/change_list_processor_unittest.cc | 45 ++--- chrome/browser/chromeos/drive/directory_loader.cc | 213 ++++++++++++++------- chrome/browser/chromeos/drive/directory_loader.h | 16 +- .../chromeos/drive/directory_loader_unittest.cc | 2 + 6 files changed, 219 insertions(+), 141 deletions(-) diff --git a/chrome/browser/chromeos/drive/change_list_processor.cc b/chrome/browser/chromeos/drive/change_list_processor.cc index b84a62028f8f..5ef384d37927 100644 --- a/chrome/browser/chromeos/drive/change_list_processor.cc +++ b/chrome/browser/chromeos/drive/change_list_processor.cc @@ -383,8 +383,8 @@ FileError ChangeListProcessor::ApplyEntry(const ResourceEntry& entry) { FileError ChangeListProcessor::RefreshDirectory( ResourceMetadata* resource_metadata, const DirectoryFetchInfo& directory_fetch_info, - ScopedVector change_lists, - base::FilePath* out_file_path) { + scoped_ptr change_list, + std::vector* out_refreshed_entries) { DCHECK(!directory_fetch_info.empty()); ResourceEntry directory; @@ -396,52 +396,45 @@ FileError ChangeListProcessor::RefreshDirectory( if (!directory.file_info().is_directory()) return FILE_ERROR_NOT_A_DIRECTORY; - for (size_t i = 0; i < change_lists.size(); ++i) { - ChangeList* change_list = change_lists[i]; - std::vector* 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::vector* 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; + } - 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); - } + entry->set_parent_local_id(directory_fetch_info.local_id()); - if (error == FILE_ERROR_NOT_FOUND) { // If refreshing fails, try adding. - std::string local_id; - entry->clear_local_id(); - error = resource_metadata->AddEntry(*entry, &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_OK) - return error; + if (error == FILE_ERROR_NOT_FOUND) { // If refreshing fails, try adding. + entry->clear_local_id(); + error = resource_metadata->AddEntry(*entry, &local_id); } - } - directory.mutable_directory_specific_info()->set_changestamp( - directory_fetch_info.changestamp()); - error = resource_metadata->RefreshEntry(directory); - if (error != FILE_ERROR_OK) - return error; + if (error != FILE_ERROR_OK) + return error; - *out_file_path = resource_metadata->GetFilePath( - directory_fetch_info.local_id()); + 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; } diff --git a/chrome/browser/chromeos/drive/change_list_processor.h b/chrome/browser/chromeos/drive/change_list_processor.h index 5a219c1c47b1..56a8fb362ded 100644 --- a/chrome/browser/chromeos/drive/change_list_processor.h +++ b/chrome/browser/chromeos/drive/change_list_processor.h @@ -122,13 +122,12 @@ class ChangeListProcessor { // The set of changed directories as a result of change list processing. const std::set& changed_dirs() const { return changed_dirs_; } - // Updates the changestamp of a directory according to |directory_fetch_info| - // and adds or refreshes the child entries from |change_lists|. + // Adds or refreshes the child entries from |change_list| to the directory. static FileError RefreshDirectory( ResourceMetadata* resource_metadata, const DirectoryFetchInfo& directory_fetch_info, - ScopedVector change_lists, - base::FilePath* out_file_path); + scoped_ptr change_list, + std::vector* out_refreshed_entries); // Sets |entry|'s parent_local_id. static FileError SetParentLocalIdOfEntry( diff --git a/chrome/browser/chromeos/drive/change_list_processor_unittest.cc b/chrome/browser/chromeos/drive/change_list_processor_unittest.cc index 18e5908823e9..c5bbc87030c1 100644 --- a/chrome/browser/chromeos/drive/change_list_processor_unittest.cc +++ b/chrome/browser/chromeos/drive/change_list_processor_unittest.cc @@ -505,45 +505,38 @@ TEST_F(ChangeListProcessorTest, RefreshDirectory) { EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(ParseChangeList(kBaseResourceListFile))); - // Create change lists. - ScopedVector change_lists; - change_lists.push_back(new ChangeList); + // Create change list. + scoped_ptr change_list(new ChangeList); - // Add a new file to the change lists. + // Add a new file to the change list. ResourceEntry new_file; new_file.set_title("new_file"); new_file.set_resource_id("new_file_id"); - change_lists[0]->mutable_entries()->push_back(new_file); - change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); + change_list->mutable_entries()->push_back(new_file); + change_list->mutable_parent_resource_ids()->push_back(kRootId); // Add "Directory 1" to the map with a new name. ResourceEntry dir1; EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( util::GetDriveMyDriveRootPath().AppendASCII("Directory 1"), &dir1)); dir1.set_title(dir1.title() + " (renamed)"); - change_lists[0]->mutable_entries()->push_back(dir1); - change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); + change_list->mutable_entries()->push_back(dir1); + change_list->mutable_parent_resource_ids()->push_back(kRootId); // Update the directory with the map. ResourceEntry root; EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( util::GetDriveMyDriveRootPath(), &root)); const int64 kNewChangestamp = 12345; - base::FilePath file_path; + ResourceEntryVector refreshed_entries; EXPECT_EQ(FILE_ERROR_OK, ChangeListProcessor::RefreshDirectory( metadata_.get(), DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp), - change_lists.Pass(), - &file_path)); - EXPECT_EQ(util::GetDriveMyDriveRootPath().value(), file_path.value()); - - // The new changestamp should be set. - ResourceEntry entry; - EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( - util::GetDriveMyDriveRootPath(), &entry)); - EXPECT_EQ(kNewChangestamp, entry.directory_specific_info().changestamp()); + change_list.Pass(), + &refreshed_entries)); // "new_file" should be added. + ResourceEntry entry; EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry)); @@ -557,16 +550,15 @@ TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) { EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(ParseChangeList(kBaseResourceListFile))); - // Create change lists and add a new file to it. - ScopedVector change_lists; - change_lists.push_back(new ChangeList); + // Create change list and add a new file to it. + scoped_ptr change_list(new ChangeList); ResourceEntry new_file; new_file.set_title("new_file"); new_file.set_resource_id("new_file_id"); // This entry should not be added because the parent ID does not match. - change_lists[0]->mutable_parent_resource_ids()->push_back( + change_list->mutable_parent_resource_ids()->push_back( "some-random-resource-id"); - change_lists[0]->mutable_entries()->push_back(new_file); + change_list->mutable_entries()->push_back(new_file); // Update the directory. @@ -574,13 +566,12 @@ TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) { EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( util::GetDriveMyDriveRootPath(), &root)); const int64 kNewChangestamp = 12345; - base::FilePath file_path; + ResourceEntryVector refreshed_entries; EXPECT_EQ(FILE_ERROR_OK, ChangeListProcessor::RefreshDirectory( metadata_.get(), DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp), - change_lists.Pass(), - &file_path)); - EXPECT_EQ(util::GetDriveMyDriveRootPath().value(), file_path.value()); + change_list.Pass(), + &refreshed_entries)); // "new_file" should not be added. ResourceEntry entry; diff --git a/chrome/browser/chromeos/drive/directory_loader.cc b/chrome/browser/chromeos/drive/directory_loader.cc index 1e3a51d45b28..9f1f04597905 100644 --- a/chrome/browser/chromeos/drive/directory_loader.cc +++ b/chrome/browser/chromeos/drive/directory_loader.cc @@ -61,35 +61,46 @@ FileError CheckLocalState(ResourceMetadata* resource_metadata, return FILE_ERROR_OK; } -void ReadDirectoryAfterRead(const std::vector& callbacks, - scoped_ptr entries, - FileError error) { +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) - entries.reset(); - for (size_t i = 0; i < callbacks.size(); ++i) { - scoped_ptr copied_entries; - if (entries) - copied_entries.reset(new ResourceEntryVector(*entries)); + return error; - callbacks[i].Run(error, copied_entries.Pass(), false /*has_more*/); - } + 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. + *directory_path = resource_metadata->GetFilePath( + directory_fetch_info.local_id()); + return FILE_ERROR_OK; } } // namespace +struct DirectoryLoader::ReadDirectoryCallbackState { + ReadDirectoryCallback callback; + std::set sent_entry_names; +}; + // Fetches the resource entries in the directory with |directory_resource_id|. class DirectoryLoader::FeedFetcher { public: - typedef base::Callback)> - FeedFetcherCallback; - - FeedFetcher(JobScheduler* scheduler, - DriveServiceInterface* drive_service, - const std::string& directory_resource_id, + FeedFetcher(DirectoryLoader* loader, + const DirectoryFetchInfo& directory_fetch_info, const std::string& root_folder_id) - : scheduler_(scheduler), - drive_service_(drive_service), - directory_resource_id_(directory_resource_id), + : loader_(loader), + directory_fetch_info_(directory_fetch_info), root_folder_id_(root_folder_id), weak_ptr_factory_(this) { } @@ -97,10 +108,10 @@ class DirectoryLoader::FeedFetcher { ~FeedFetcher() { } - void Run(const FeedFetcherCallback& callback) { + void Run(const FileOperationCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!callback.is_null()); - DCHECK(!directory_resource_id_.empty()); + DCHECK(!directory_fetch_info_.resource_id().empty()); // Remember the time stamp for usage stats. start_time_ = base::TimeTicks::Now(); @@ -110,14 +121,14 @@ class DirectoryLoader::FeedFetcher { // regression. // TODO(hashimoto): Remove this. crbug.com/340931. - std::string resource_id = directory_resource_id_; - if (directory_resource_id_ == root_folder_id_) { + std::string resource_id = directory_fetch_info_.resource_id(); + if (resource_id == root_folder_id_) { // GData WAPI doesn't accept the root directory id which is used in Drive // API v2. So it is necessary to translate it here. resource_id = util::kWapiRootDirectoryResourceId; } - scheduler_->GetResourceListInDirectoryByWapi( + loader_->scheduler_->GetResourceListInDirectoryByWapi( resource_id, base::Bind(&FeedFetcher::OnResourceListFetched, weak_ptr_factory_.GetWeakPtr(), callback)); @@ -125,7 +136,7 @@ class DirectoryLoader::FeedFetcher { private: void OnResourceListFetched( - const FeedFetcherCallback& callback, + const FileOperationCallback& callback, google_apis::GDataErrorCode status, scoped_ptr resource_list) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -133,20 +144,54 @@ class DirectoryLoader::FeedFetcher { FileError error = GDataToFileError(status); if (error != FILE_ERROR_OK) { - callback.Run(error, ScopedVector()); + callback.Run(error); return; } - // Add the current change list to the list of collected lists. DCHECK(resource_list); - ChangeList* change_list = new ChangeList(*resource_list); - FixResourceIdInChangeList(change_list); - change_lists_.push_back(change_list); + scoped_ptr change_list(new ChangeList(*resource_list)); + FixResourceIdInChangeList(change_list.get()); GURL next_url; - if (resource_list->GetNextFeedURL(&next_url) && !next_url.is_empty()) { + resource_list->GetNextFeedURL(&next_url); + + ResourceEntryVector* entries = new ResourceEntryVector; + loader_->loader_controller_->ScheduleRun(base::Bind( + base::IgnoreResult( + &base::PostTaskAndReplyWithResult), + 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* refreshed_entries, + FileError error) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(!callback.is_null()); + + if (error != FILE_ERROR_OK) { + callback.Run(error); + return; + } + + loader_->SendEntries(directory_fetch_info_.local_id(), *refreshed_entries, + true /*has_more*/); + + if (!next_url.is_empty()) { // There is the remaining result so fetch it. - scheduler_->GetRemainingResourceList( + loader_->scheduler_->GetRemainingResourceList( next_url, base::Bind(&FeedFetcher::OnResourceListFetched, weak_ptr_factory_.GetWeakPtr(), callback)); @@ -159,7 +204,7 @@ class DirectoryLoader::FeedFetcher { // 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, change_lists_.Pass()); + callback.Run(FILE_ERROR_OK); } // Fixes resource IDs in |change_list| into the format that |drive_service_| @@ -181,14 +226,13 @@ class DirectoryLoader::FeedFetcher { std::string FixResourceId(const std::string& resource_id) { if (resource_id == util::kWapiRootDirectoryResourceId) return root_folder_id_; - return drive_service_->GetResourceIdCanonicalizer().Run(resource_id); + return loader_->drive_service_->GetResourceIdCanonicalizer().Run( + resource_id); } - JobScheduler* scheduler_; - DriveServiceInterface* drive_service_; - std::string directory_resource_id_; + DirectoryLoader* loader_; + DirectoryFetchInfo directory_fetch_info_; std::string root_folder_id_; - ScopedVector change_lists_; base::TimeTicks start_time_; base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(FeedFetcher); @@ -285,7 +329,9 @@ void DirectoryLoader::ReadDirectoryAfterGetEntry( // Register the callback function to be called when it is loaded. const std::string& local_id = directory_fetch_info.local_id(); - pending_load_callback_[local_id].push_back(callback); + ReadDirectoryCallbackState callback_state; + callback_state.callback = 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) @@ -427,22 +473,64 @@ void DirectoryLoader::OnDirectoryLoadComplete(const std::string& local_id, "Fast-fetch complete: %s => %s", local_id.c_str(), FileErrorToString(error).c_str()); + + 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; - const std::vector& callbacks = it->second; - 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(&ReadDirectoryAfterRead, callbacks, - base::Passed(scoped_ptr(entries)))); + + const bool kHasMore = false; + if (error == FILE_ERROR_OK) { + SendEntries(local_id, *entries, kHasMore); + } else { + for (size_t i = 0; i < it->second.size(); ++i) { + const ReadDirectoryCallbackState& callback_state = it->second[i]; + callback_state.callback.Run(error, scoped_ptr(), + kHasMore); + } + } pending_load_callback_.erase(it); } } +void DirectoryLoader::SendEntries(const std::string& local_id, + const ResourceEntryVector& entries, + bool has_more) { + 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]; + + // Filter out entries which were already sent. + scoped_ptr 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->callback.Run(FILE_ERROR_OK, entries_to_send.Pass(), + has_more); + } +} + void DirectoryLoader::LoadDirectoryFromServer( const DirectoryFetchInfo& directory_fetch_info) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -451,9 +539,8 @@ void DirectoryLoader::LoadDirectoryFromServer( DVLOG(1) << "Start loading directory: " << directory_fetch_info.ToString(); FeedFetcher* fetcher = new FeedFetcher( - scheduler_, - drive_service_, - directory_fetch_info.resource_id(), + this, + directory_fetch_info, about_resource_loader_->cached_about_resource()->root_folder_id()); fast_fetch_feed_fetcher_set_.insert(fetcher); fetcher->Run( @@ -466,8 +553,7 @@ void DirectoryLoader::LoadDirectoryFromServer( void DirectoryLoader::LoadDirectoryFromServerAfterLoad( const DirectoryFetchInfo& directory_fetch_info, FeedFetcher* fetcher, - FileError error, - ScopedVector change_lists) { + FileError error) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!directory_fetch_info.empty()); @@ -483,24 +569,23 @@ void DirectoryLoader::LoadDirectoryFromServerAfterLoad( return; } + // Update changestamp and get the directory path. base::FilePath* directory_path = new base::FilePath; - loader_controller_->ScheduleRun(base::Bind( - base::IgnoreResult( - &base::PostTaskAndReplyWithResult), - blocking_task_runner_, + base::PostTaskAndReplyWithResult( + blocking_task_runner_.get(), FROM_HERE, - base::Bind(&ChangeListProcessor::RefreshDirectory, + base::Bind(&UpdateChangestamp, resource_metadata_, directory_fetch_info, - base::Passed(&change_lists), directory_path), - base::Bind(&DirectoryLoader::LoadDirectoryFromServerAfterRefresh, - weak_ptr_factory_.GetWeakPtr(), - directory_fetch_info, - base::Owned(directory_path)))); + base::Bind( + &DirectoryLoader::LoadDirectoryFromServerAfterUpdateChangestamp, + weak_ptr_factory_.GetWeakPtr(), + directory_fetch_info, + base::Owned(directory_path))); } -void DirectoryLoader::LoadDirectoryFromServerAfterRefresh( +void DirectoryLoader::LoadDirectoryFromServerAfterUpdateChangestamp( const DirectoryFetchInfo& directory_fetch_info, const base::FilePath* directory_path, FileError error) { diff --git a/chrome/browser/chromeos/drive/directory_loader.h b/chrome/browser/chromeos/drive/directory_loader.h index 63b60a755cbe..723bf01af7a6 100644 --- a/chrome/browser/chromeos/drive/directory_loader.h +++ b/chrome/browser/chromeos/drive/directory_loader.h @@ -67,6 +67,7 @@ class DirectoryLoader { private: class FeedFetcher; + struct ReadDirectoryCallbackState; // Part of ReadDirectory(). void ReadDirectoryAfterGetEntry(const base::FilePath& directory_path, @@ -94,6 +95,14 @@ class DirectoryLoader { // This function should be called when the directory load is complete. // Flushes the callbacks waiting for the directory to be loaded. void OnDirectoryLoadComplete(const std::string& local_id, FileError error); + void OnDirectoryLoadCompleteAfterRead(const std::string& local_id, + const ResourceEntryVector* entries, + FileError error); + + // Sends |entries| to the callbacks. + void SendEntries(const std::string& local_id, + const ResourceEntryVector& entries, + bool has_more); // ================= Implementation for directory loading ================= // Loads the directory contents from server, and updates the local metadata. @@ -104,11 +113,10 @@ class DirectoryLoader { void LoadDirectoryFromServerAfterLoad( const DirectoryFetchInfo& directory_fetch_info, FeedFetcher* fetcher, - FileError error, - ScopedVector change_lists); + FileError error); // Part of LoadDirectoryFromServer(). - void LoadDirectoryFromServerAfterRefresh( + void LoadDirectoryFromServerAfterUpdateChangestamp( const DirectoryFetchInfo& directory_fetch_info, const base::FilePath* directory_path, FileError error); @@ -121,7 +129,7 @@ class DirectoryLoader { AboutResourceLoader* about_resource_loader_; // Not owned. LoaderController* loader_controller_; // Not owned. ObserverList observers_; - typedef std::map > + typedef std::map > LoadCallbackMap; LoadCallbackMap pending_load_callback_; diff --git a/chrome/browser/chromeos/drive/directory_loader_unittest.cc b/chrome/browser/chromeos/drive/directory_loader_unittest.cc index e42631673fbb..bb93d4bc6c9b 100644 --- a/chrome/browser/chromeos/drive/directory_loader_unittest.cc +++ b/chrome/browser/chromeos/drive/directory_loader_unittest.cc @@ -206,6 +206,8 @@ TEST_F(DirectoryLoaderTest, ReadDirectory_MyDrive) { metadata_->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(), &entry)); EXPECT_EQ(drive_service_->GetRootResourceId(), entry.resource_id()); + EXPECT_EQ(drive_service_->about_resource().largest_change_id(), + entry.directory_specific_info().changestamp()); // My Drive's child is present. base::FilePath file_path = -- 2.11.4.GIT