Commit 16fe0824 authored by kinaba@chromium.org's avatar kinaba@chromium.org

Sort methods of drive::ChangeListLoader.

Made header and source ordering consistent.
And more importantly, grouped relevant methods as much as possible, and
sorted in the order of execution, so that the source code is easily read
from top to bottom.

BUG=none.

Review URL: https://codereview.chromium.org/13896005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194794 0039d316-1c4b-4281-b951-d872f2087c98
parent 663c4b35
...@@ -52,6 +52,218 @@ void ChangeListLoader::RemoveObserver(ChangeListLoaderObserver* observer) { ...@@ -52,6 +52,218 @@ void ChangeListLoader::RemoveObserver(ChangeListLoaderObserver* observer) {
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
void ChangeListLoader::CheckForUpdates(const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
if (loaded_ && !IsRefreshing())
Load(DirectoryFetchInfo(), callback);
}
void ChangeListLoader::LoadIfNeeded(
const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
// If feed has already been loaded, for normal feed fetch (= empty
// directory_fetch_info), we have nothing to do. For "fast fetch", we need to
// schedule a fetching if a feed refresh is currently running, because we
// don't want to wait a possibly large delta feed to arrive.
if (loaded_ && (directory_fetch_info.empty() || !IsRefreshing())) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(callback, DRIVE_FILE_OK));
return;
}
Load(directory_fetch_info, callback);
}
void ChangeListLoader::LoadDirectoryFromServer(
const std::string& directory_resource_id,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
// First fetch the latest changestamp to see if this directory needs to be
// updated.
scheduler_->GetAboutResource(
base::Bind(
&ChangeListLoader::LoadDirectoryFromServerAfterGetAbout,
weak_ptr_factory_.GetWeakPtr(),
directory_resource_id,
callback));
}
void ChangeListLoader::SearchFromServer(
const std::string& search_query,
const GURL& next_feed,
const LoadFeedListCallback& callback) {
DCHECK(!callback.is_null());
if (next_feed.is_empty()) {
// This is first request for the |search_query|.
scheduler_->Search(
search_query,
base::Bind(&ChangeListLoader::SearchFromServerAfterGetResourceList,
weak_ptr_factory_.GetWeakPtr(), callback));
} else {
// There is the remaining result so fetch it.
scheduler_->ContinueGetResourceList(
next_feed,
base::Bind(&ChangeListLoader::SearchFromServerAfterGetResourceList,
weak_ptr_factory_.GetWeakPtr(), callback));
}
}
void ChangeListLoader::UpdateFromFeed(
scoped_ptr<google_apis::AboutResource> about_resource,
ScopedVector<ChangeList> change_lists,
bool is_delta_feed,
const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
change_list_processor_.reset(new ChangeListProcessor(resource_metadata_));
// Don't send directory content change notification while performing
// the initial content retrieval.
const bool should_notify_changed_directories = is_delta_feed;
change_list_processor_->ApplyFeeds(
about_resource.Pass(),
change_lists.Pass(),
is_delta_feed,
base::Bind(&ChangeListLoader::NotifyDirectoryChangedAfterApplyFeed,
weak_ptr_factory_.GetWeakPtr(),
should_notify_changed_directories,
callback));
}
void ChangeListLoader::Load(const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
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.
const std::string& resource_id = directory_fetch_info.resource_id();
pending_load_callback_[resource_id].push_back(callback);
// If loading task for |resource_id| is already running, do nothing.
if (pending_load_callback_[resource_id].size() > 1)
return;
// For initial loading, even for directory fetching, we do load the full
// feed from the server to sync up. So we register a dummy callback to
// indicate that update for full hierarchy is running.
if (is_initial_load && !resource_id.empty()) {
pending_load_callback_[""].push_back(
base::Bind(&util::EmptyFileOperationCallback));
}
// Check the current status of local metadata, and start loading if needed.
resource_metadata_->GetLargestChangestamp(
base::Bind(is_initial_load ? &ChangeListLoader::DoInitialLoad
: &ChangeListLoader::DoUpdateLoad,
weak_ptr_factory_.GetWeakPtr(),
directory_fetch_info));
}
void ChangeListLoader::DoInitialLoad(
const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (local_changestamp > 0) {
// The local data is usable. Flush callbacks to tell loading was successful.
OnChangeListLoadComplete(DRIVE_FILE_OK);
// Continues to load from server in background.
// Put dummy callbacks to indicate that fetching is still continuing.
pending_load_callback_[directory_fetch_info.resource_id()].push_back(
base::Bind(&util::EmptyFileOperationCallback));
if (!directory_fetch_info.empty()) {
pending_load_callback_[""].push_back(
base::Bind(&util::EmptyFileOperationCallback));
}
}
LoadFromServerIfNeeded(directory_fetch_info, local_changestamp);
}
void ChangeListLoader::DoUpdateLoad(
const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (directory_fetch_info.empty()) {
LoadFromServerIfNeeded(directory_fetch_info, local_changestamp);
} else {
// Note: CheckChangestampAndLoadDirectoryIfNeeded regards
// last_know_remote_changestamp_ as the remote changestamp. To be precise,
// we need to call GetAboutResource() here, as we do in other places like
// LoadFromServerIfNeeded or LoadFromDirectory. However,
// - It is costly to do GetAboutResource HTTP request every time.
// - The chance using an old value is small; it only happens when
// LoadIfNeeded is called during one GetAboutResource roundtrip time
// of a feed fetching.
// - Even if the value is old, it just marks the directory as older. It may
// trigger one future unnecessary re-fetch, but it'll never lose data.
CheckChangestampAndLoadDirectoryIfNeeed(
directory_fetch_info,
local_changestamp,
base::Bind(&ChangeListLoader::OnDirectoryLoadComplete,
weak_ptr_factory_.GetWeakPtr(),
directory_fetch_info));
}
}
void ChangeListLoader::OnChangeListLoadComplete(DriveFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!loaded_ && error == DRIVE_FILE_OK) {
loaded_ = true;
FOR_EACH_OBSERVER(ChangeListLoaderObserver,
observers_,
OnInitialFeedLoaded());
}
for (LoadCallbackMap::iterator it = pending_load_callback_.begin();
it != pending_load_callback_.end(); ++it) {
const std::vector<FileOperationCallback>& callbacks = it->second;
for (size_t i = 0; i < callbacks.size(); ++i) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(callbacks[i], error));
}
}
pending_load_callback_.clear();
}
void ChangeListLoader::OnDirectoryLoadComplete(
const DirectoryFetchInfo& directory_fetch_info,
DriveFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DVLOG_IF(1, error == DRIVE_FILE_OK) << "Fast-fetch was successful: "
<< directory_fetch_info.ToString();
const std::string& resource_id = directory_fetch_info.resource_id();
LoadCallbackMap::iterator it = pending_load_callback_.find(resource_id);
if (it != pending_load_callback_.end()) {
DVLOG(1) << "Running callback for " << resource_id;
const std::vector<FileOperationCallback>& callbacks = it->second;
for (size_t i = 0; i < callbacks.size(); ++i) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(callbacks[i], error));
}
pending_load_callback_.erase(it);
}
}
void ChangeListLoader::LoadFromServerIfNeeded( void ChangeListLoader::LoadFromServerIfNeeded(
const DirectoryFetchInfo& directory_fetch_info, const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp) { int64 local_changestamp) {
...@@ -140,6 +352,22 @@ void ChangeListLoader::LoadFromServerIfNeededAfterGetAbout( ...@@ -140,6 +352,22 @@ void ChangeListLoader::LoadFromServerIfNeededAfterGetAbout(
} }
} }
void ChangeListLoader::LoadChangeListFromServerAfterLoadDirectory(
const DirectoryFetchInfo& directory_fetch_info,
scoped_ptr<google_apis::AboutResource> about_resource,
int64 start_changestamp,
DriveFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (error == DRIVE_FILE_OK) {
// The directory fast-fetch succeeded. Runs the callbacks waiting for the
// directory loading. If failed, do not flush so they're run after the
// change list loading is complete.
OnDirectoryLoadComplete(directory_fetch_info, DRIVE_FILE_OK);
}
LoadChangeListFromServer(about_resource.Pass(), start_changestamp);
}
void ChangeListLoader::LoadChangeListFromServer( void ChangeListLoader::LoadChangeListFromServer(
scoped_ptr<google_apis::AboutResource> about_resource, scoped_ptr<google_apis::AboutResource> about_resource,
int64 start_changestamp) { int64 start_changestamp) {
...@@ -171,55 +399,6 @@ void ChangeListLoader::LoadChangeListFromServer( ...@@ -171,55 +399,6 @@ void ChangeListLoader::LoadChangeListFromServer(
} }
} }
void ChangeListLoader::LoadChangeListFromServerAfterLoadDirectory(
const DirectoryFetchInfo& directory_fetch_info,
scoped_ptr<google_apis::AboutResource> about_resource,
int64 start_changestamp,
DriveFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (error == DRIVE_FILE_OK) {
// The directory fast-fetch succeeded. Runs the callbacks waiting for the
// directory loading. If failed, do not flush so they're run after the
// change list loading is complete.
OnDirectoryLoadComplete(directory_fetch_info, DRIVE_FILE_OK);
}
LoadChangeListFromServer(about_resource.Pass(), start_changestamp);
}
void ChangeListLoader::SearchFromServerAfterGetResourceList(
const LoadFeedListCallback& callback,
google_apis::GDataErrorCode status,
scoped_ptr<google_apis::ResourceList> resource_list) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
DriveFileError error = util::GDataToDriveFileError(status);
if (error != DRIVE_FILE_OK) {
callback.Run(ScopedVector<ChangeList>(), error);
return;
}
DCHECK(resource_list);
ScopedVector<ChangeList> change_lists;
change_lists.push_back(new ChangeList(*resource_list));
callback.Run(change_lists.Pass(), DRIVE_FILE_OK);
}
void ChangeListLoader::OnGetAppList(google_apis::GDataErrorCode status,
scoped_ptr<google_apis::AppList> app_list) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DriveFileError error = util::GDataToDriveFileError(status);
if (error != DRIVE_FILE_OK)
return;
if (app_list.get()) {
webapps_registry_->UpdateFromAppList(*app_list);
}
}
void ChangeListLoader::OnGetResourceList( void ChangeListLoader::OnGetResourceList(
ScopedVector<ChangeList> change_lists, ScopedVector<ChangeList> change_lists,
const LoadFeedListCallback& callback, const LoadFeedListCallback& callback,
...@@ -268,20 +447,33 @@ void ChangeListLoader::OnGetResourceList( ...@@ -268,20 +447,33 @@ void ChangeListLoader::OnGetResourceList(
callback.Run(change_lists.Pass(), DRIVE_FILE_OK); callback.Run(change_lists.Pass(), DRIVE_FILE_OK);
} }
void ChangeListLoader::LoadDirectoryFromServer( void ChangeListLoader::UpdateMetadataFromFeedAfterLoadFromServer(
const std::string& directory_resource_id, scoped_ptr<google_apis::AboutResource> about_resource,
const FileOperationCallback& callback) { bool is_delta_feed,
ScopedVector<ChangeList> change_lists,
DriveFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
// First fetch the latest changestamp to see if this directory needs to be if (error != DRIVE_FILE_OK) {
// updated. OnChangeListLoadComplete(error);
scheduler_->GetAboutResource( return;
base::Bind( }
&ChangeListLoader::LoadDirectoryFromServerAfterGetAbout,
weak_ptr_factory_.GetWeakPtr(), UpdateFromFeed(about_resource.Pass(),
directory_resource_id, change_lists.Pass(),
callback)); is_delta_feed,
base::Bind(&ChangeListLoader::OnUpdateFromFeed,
weak_ptr_factory_.GetWeakPtr()));
}
void ChangeListLoader::OnUpdateFromFeed() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
OnChangeListLoadComplete(DRIVE_FILE_OK);
FOR_EACH_OBSERVER(ChangeListLoaderObserver,
observers_,
OnFeedFromServerLoaded());
} }
void ChangeListLoader::LoadDirectoryFromServerAfterGetAbout( void ChangeListLoader::LoadDirectoryFromServerAfterGetAbout(
...@@ -303,6 +495,37 @@ void ChangeListLoader::LoadDirectoryFromServerAfterGetAbout( ...@@ -303,6 +495,37 @@ void ChangeListLoader::LoadDirectoryFromServerAfterGetAbout(
DoLoadDirectoryFromServer(directory_fetch_info, callback); DoLoadDirectoryFromServer(directory_fetch_info, callback);
} }
void ChangeListLoader::CheckChangestampAndLoadDirectoryIfNeeed(
const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!directory_fetch_info.empty());
int64 directory_changestamp = std::max(directory_fetch_info.changestamp(),
local_changestamp);
// If the directory's changestamp is up-to-date, just schedule to run the
// callback, as there is no need to fetch the directory.
// Note that |last_known_remote_changestamp_| is 0 when it is not received
// yet. In that case we conservatively assume that we need to fetch.
if (last_known_remote_changestamp_ > 0 &&
directory_changestamp >= last_known_remote_changestamp_) {
callback.Run(DRIVE_FILE_OK);
return;
}
DVLOG(1) << "Fast-fetching directory: " << directory_fetch_info.ToString()
<< "; remote_changestamp: " << last_known_remote_changestamp_;
// Start fetching the directory content, and mark it with the changestamp
// |last_known_remote_changestamp_|.
DirectoryFetchInfo new_directory_fetch_info(
directory_fetch_info.resource_id(),
std::max(directory_changestamp, last_known_remote_changestamp_));
DoLoadDirectoryFromServer(new_directory_fetch_info, callback);
}
void ChangeListLoader::DoLoadDirectoryFromServer( void ChangeListLoader::DoLoadDirectoryFromServer(
const DirectoryFetchInfo& directory_fetch_info, const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback) { const FileOperationCallback& callback) {
...@@ -459,214 +682,44 @@ void ChangeListLoader::DoLoadDirectoryFromServerAfterRefresh( ...@@ -459,214 +682,44 @@ void ChangeListLoader::DoLoadDirectoryFromServerAfterRefresh(
} }
} }
void ChangeListLoader::SearchFromServer( void ChangeListLoader::OnGetAppList(google_apis::GDataErrorCode status,
const std::string& search_query, scoped_ptr<google_apis::AppList> app_list) {
const GURL& next_feed,
const LoadFeedListCallback& callback) {
DCHECK(!callback.is_null());
if (next_feed.is_empty()) {
// This is first request for the |search_query|.
scheduler_->Search(
search_query,
base::Bind(&ChangeListLoader::SearchFromServerAfterGetResourceList,
weak_ptr_factory_.GetWeakPtr(), callback));
} else {
// There is the remaining result so fetch it.
scheduler_->ContinueGetResourceList(
next_feed,
base::Bind(&ChangeListLoader::SearchFromServerAfterGetResourceList,
weak_ptr_factory_.GetWeakPtr(), callback));
}
}
void ChangeListLoader::UpdateMetadataFromFeedAfterLoadFromServer(
scoped_ptr<google_apis::AboutResource> about_resource,
bool is_delta_feed,
ScopedVector<ChangeList> change_lists,
DriveFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (error != DRIVE_FILE_OK) {
OnChangeListLoadComplete(error);
return;
}
UpdateFromFeed(about_resource.Pass(),
change_lists.Pass(),
is_delta_feed,
base::Bind(&ChangeListLoader::OnUpdateFromFeed,
weak_ptr_factory_.GetWeakPtr()));
}
void ChangeListLoader::LoadIfNeeded(
const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
// If feed has already been loaded, for normal feed fetch (= empty
// directory_fetch_info), we have nothing to do. For "fast fetch", we need to
// schedule a fetching if a feed refresh is currently running, because we
// don't want to wait a possibly large delta feed to arrive.
if (loaded_ && (directory_fetch_info.empty() || !IsRefreshing())) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(callback, DRIVE_FILE_OK));
return;
}
Load(directory_fetch_info, callback);
}
void ChangeListLoader::Load(const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
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.
const std::string& resource_id = directory_fetch_info.resource_id();
pending_load_callback_[resource_id].push_back(callback);
// If loading task for |resource_id| is already running, do nothing. DriveFileError error = util::GDataToDriveFileError(status);
if (pending_load_callback_[resource_id].size() > 1) if (error != DRIVE_FILE_OK)
return; return;
// For initial loading, even for directory fetching, we do load the full if (app_list.get())
// feed from the server to sync up. So we register a dummy callback to webapps_registry_->UpdateFromAppList(*app_list);
// indicate that update for full hierarchy is running.
if (is_initial_load && !resource_id.empty()) {
pending_load_callback_[""].push_back(
base::Bind(&util::EmptyFileOperationCallback));
}
// Check the current status of local metadata, and start loading if needed.
resource_metadata_->GetLargestChangestamp(
base::Bind(is_initial_load ? &ChangeListLoader::DoInitialLoad
: &ChangeListLoader::DoUpdateLoad,
weak_ptr_factory_.GetWeakPtr(),
directory_fetch_info));
}
void ChangeListLoader::DoInitialLoad(
const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (local_changestamp > 0) {
// The local data is usable. Flush callbacks to tell loading was successful.
OnChangeListLoadComplete(DRIVE_FILE_OK);
// Continues to load from server in background.
// Put dummy callbacks to indicate that fetching is still continuing.
pending_load_callback_[directory_fetch_info.resource_id()].push_back(
base::Bind(&util::EmptyFileOperationCallback));
if (!directory_fetch_info.empty()) {
pending_load_callback_[""].push_back(
base::Bind(&util::EmptyFileOperationCallback));
}
}
LoadFromServerIfNeeded(directory_fetch_info, local_changestamp);
}
void ChangeListLoader::DoUpdateLoad(
const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (directory_fetch_info.empty()) {
LoadFromServerIfNeeded(directory_fetch_info, local_changestamp);
} else {
// Note: CheckChangestampAndLoadDirectoryIfNeeded regards
// last_know_remote_changestamp_ as the remote changestamp. To be precise,
// we need to call GetAboutResource() here, as we do in other places like
// LoadFromServerIfNeeded or LoadFromDirectory. However,
// - It is costly to do GetAboutResource HTTP request every time.
// - The chance using an old value is small; it only happens when
// LoadIfNeeded is called during one GetAboutResource roundtrip time
// of a feed fetching.
// - Even if the value is old, it just marks the directory as older. It may
// trigger one future unnecessary re-fetch, but it'll never lose data.
CheckChangestampAndLoadDirectoryIfNeeed(
directory_fetch_info,
local_changestamp,
base::Bind(&ChangeListLoader::OnDirectoryLoadComplete,
weak_ptr_factory_.GetWeakPtr(),
directory_fetch_info));
}
} }
void ChangeListLoader::CheckForUpdates(const FileOperationCallback& callback) { void ChangeListLoader::SearchFromServerAfterGetResourceList(
const LoadFeedListCallback& callback,
google_apis::GDataErrorCode status,
scoped_ptr<google_apis::ResourceList> resource_list) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
if (loaded_ && !IsRefreshing()) DriveFileError error = util::GDataToDriveFileError(status);
Load(DirectoryFetchInfo(), callback); if (error != DRIVE_FILE_OK) {
} callback.Run(ScopedVector<ChangeList>(), error);
void ChangeListLoader::UpdateFromFeed(
scoped_ptr<google_apis::AboutResource> about_resource,
ScopedVector<ChangeList> change_lists,
bool is_delta_feed,
const base::Closure& update_finished_callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!update_finished_callback.is_null());
change_list_processor_.reset(new ChangeListProcessor(resource_metadata_));
// Don't send directory content change notification while performing
// the initial content retrieval.
const bool should_notify_changed_directories = is_delta_feed;
change_list_processor_->ApplyFeeds(
about_resource.Pass(),
change_lists.Pass(),
is_delta_feed,
base::Bind(&ChangeListLoader::NotifyDirectoryChangedAfterApplyFeed,
weak_ptr_factory_.GetWeakPtr(),
should_notify_changed_directories,
update_finished_callback));
}
void ChangeListLoader::CheckChangestampAndLoadDirectoryIfNeeed(
const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp,
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!directory_fetch_info.empty());
int64 directory_changestamp = std::max(directory_fetch_info.changestamp(),
local_changestamp);
// If the directory's changestamp is up-to-date, just schedule to run the
// callback, as there is no need to fetch the directory.
// Note that |last_known_remote_changestamp_| is 0 when it is not received
// yet. In that case we conservatively assume that we need to fetch.
if (last_known_remote_changestamp_ > 0 &&
directory_changestamp >= last_known_remote_changestamp_) {
callback.Run(DRIVE_FILE_OK);
return; return;
} }
DVLOG(1) << "Fast-fetching directory: " << directory_fetch_info.ToString() DCHECK(resource_list);
<< "; remote_changestamp: " << last_known_remote_changestamp_;
// Start fetching the directory content, and mark it with the changestamp ScopedVector<ChangeList> change_lists;
// |last_known_remote_changestamp_|. change_lists.push_back(new ChangeList(*resource_list));
DirectoryFetchInfo new_directory_fetch_info( callback.Run(change_lists.Pass(), DRIVE_FILE_OK);
directory_fetch_info.resource_id(),
std::max(directory_changestamp, last_known_remote_changestamp_));
DoLoadDirectoryFromServer(new_directory_fetch_info, callback);
} }
void ChangeListLoader::NotifyDirectoryChangedAfterApplyFeed( void ChangeListLoader::NotifyDirectoryChangedAfterApplyFeed(
bool should_notify_changed_directories, bool should_notify_changed_directories,
const base::Closure& update_finished_callback) { const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(change_list_processor_.get()); DCHECK(change_list_processor_.get());
DCHECK(!update_finished_callback.is_null()); DCHECK(!callback.is_null());
if (should_notify_changed_directories) { if (should_notify_changed_directories) {
for (std::set<base::FilePath>::iterator dir_iter = for (std::set<base::FilePath>::iterator dir_iter =
...@@ -678,64 +731,10 @@ void ChangeListLoader::NotifyDirectoryChangedAfterApplyFeed( ...@@ -678,64 +731,10 @@ void ChangeListLoader::NotifyDirectoryChangedAfterApplyFeed(
} }
} }
update_finished_callback.Run(); callback.Run();
// Cannot delete change_list_processor_ yet because we are in // Cannot delete change_list_processor_ yet because we are in
// on_complete_callback_, which is owned by change_list_processor_. // on_complete_callback_, which is owned by change_list_processor_.
} }
void ChangeListLoader::OnUpdateFromFeed() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
OnChangeListLoadComplete(DRIVE_FILE_OK);
FOR_EACH_OBSERVER(ChangeListLoaderObserver,
observers_,
OnFeedFromServerLoaded());
}
void ChangeListLoader::OnChangeListLoadComplete(DriveFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!loaded_ && error == DRIVE_FILE_OK) {
loaded_ = true;
FOR_EACH_OBSERVER(ChangeListLoaderObserver,
observers_,
OnInitialFeedLoaded());
}
for (LoadCallbackMap::iterator it = pending_load_callback_.begin();
it != pending_load_callback_.end(); ++it) {
const std::vector<FileOperationCallback>& callbacks = it->second;
for (size_t i = 0; i < callbacks.size(); ++i) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(callbacks[i], error));
}
}
pending_load_callback_.clear();
}
void ChangeListLoader::OnDirectoryLoadComplete(
const DirectoryFetchInfo& directory_fetch_info,
DriveFileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DVLOG_IF(1, error == DRIVE_FILE_OK) << "Fast-fetch was successful: "
<< directory_fetch_info.ToString();
const std::string& resource_id = directory_fetch_info.resource_id();
LoadCallbackMap::iterator it = pending_load_callback_.find(resource_id);
if (it != pending_load_callback_.end()) {
DVLOG(1) << "Running callback for " << resource_id;
const std::vector<FileOperationCallback>& callbacks = it->second;
for (size_t i = 0; i < callbacks.size(); ++i) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(callbacks[i], error));
}
pending_load_callback_.erase(it);
}
}
} // namespace drive } // namespace drive
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <map> #include <map>
#include <string> #include <string>
#include <utility>
#include <vector> #include <vector>
#include "base/callback_forward.h" #include "base/callback_forward.h"
...@@ -32,7 +31,7 @@ class ChangeListProcessor; ...@@ -32,7 +31,7 @@ class ChangeListProcessor;
class DriveScheduler; class DriveScheduler;
class DriveWebAppsRegistry; class DriveWebAppsRegistry;
// Callback run as a response to SearchFromServer and LoadDirectoryFromServer. // Callback run as a response to SearchFromServer.
typedef base::Callback<void(ScopedVector<ChangeList> change_lists, typedef base::Callback<void(ScopedVector<ChangeList> change_lists,
DriveFileError error)> LoadFeedListCallback; DriveFileError error)> LoadFeedListCallback;
...@@ -45,15 +44,22 @@ class ChangeListLoader { ...@@ -45,15 +44,22 @@ class ChangeListLoader {
DriveWebAppsRegistry* webapps_registry); DriveWebAppsRegistry* webapps_registry);
~ChangeListLoader(); ~ChangeListLoader();
// Indicates whether there is a feed refreshing server request is in flight.
bool IsRefreshing() const;
// Adds and removes the observer. // Adds and removes the observer.
void AddObserver(ChangeListLoaderObserver* observer); void AddObserver(ChangeListLoaderObserver* observer);
void RemoveObserver(ChangeListLoaderObserver* observer); void RemoveObserver(ChangeListLoaderObserver* observer);
// Checks for updates on the server. Does nothing if the change list is now
// being loaded or refreshed. |callback| must not be null.
void CheckForUpdates(const FileOperationCallback& callback);
// Starts the change list loading first from the cache. If loading from the // Starts the change list loading first from the cache. If loading from the
// cache is successful, runs |callback| and starts loading from the server // cache is successful, runs |callback| immediately and starts checking
// if needed (i.e. the cache is old). If loading from the cache is // server for updates in background. If loading from the cache is
// unsuccessful, starts loading from the server, and runs |callback| to // unsuccessful, starts loading from the server, and runs |callback| to tell
// tell the result to the caller. // the result to the caller when it is finished.
// //
// If |directory_fetch_info| is not empty, the directory will be fetched // If |directory_fetch_info| is not empty, the directory will be fetched
// first from the server, so the UI can show the directory contents // first from the server, so the UI can show the directory contents
...@@ -86,29 +92,23 @@ class ChangeListLoader { ...@@ -86,29 +92,23 @@ class ChangeListLoader {
const GURL& next_feed, const GURL& next_feed,
const LoadFeedListCallback& callback); const LoadFeedListCallback& callback);
// Checks for updates on the server. Does nothing if the change list is now // TODO(satorux): Make this private. crbug.com/232208
// being loaded or refreshed. |callback| must not be null.
void CheckForUpdates(const FileOperationCallback& callback);
// Updates whole directory structure feeds collected in |feed_list|. // Updates whole directory structure feeds collected in |feed_list|.
// Record file statistics as UMA histograms. // Record file statistics as UMA histograms.
// //
// See comments at ChangeListProcessor::ApplyFeeds() for // See comments at ChangeListProcessor::ApplyFeeds() for
// |about_resource| and |is_delta_feed|. // |about_resource| and |is_delta_feed|.
// |update_finished_callback| must not be null. // |callback| must not be null.
void UpdateFromFeed(scoped_ptr<google_apis::AboutResource> about_resource, void UpdateFromFeed(scoped_ptr<google_apis::AboutResource> about_resource,
ScopedVector<ChangeList> change_lists, ScopedVector<ChangeList> change_lists,
bool is_delta_feed, bool is_delta_feed,
const base::Closure& update_finished_callback); const base::Closure& callback);
// Indicates whether there is a feed refreshing server request is in flight.
bool IsRefreshing() const;
private: private:
// Implementation of LoadIfNeeded and CheckForUpdates. Start metadata loading // Start metadata loading of |directory_fetch_info|, and calls |callback|
// of |directory_fetch_info|, and calls |callback| when it's done. If there is // when it's done. If there is already a loading job in-flight for
// already a loading job in-flight for |directory_fetch_info|, just append // |directory_fetch_info|, just append the |callback| to the callback queue
// the |callback| to the callback queue of the already running job. // of the already running job.
void Load(const DirectoryFetchInfo& directory_fetch_info, void Load(const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback); const FileOperationCallback& callback);
...@@ -125,105 +125,128 @@ class ChangeListLoader { ...@@ -125,105 +125,128 @@ class ChangeListLoader {
int64 local_changestamp); int64 local_changestamp);
// Part of Load(). // Part of Load().
// This function should be called when the change list load is complete.
// Flushes the callbacks for change list loading and all directory loading.
void OnChangeListLoadComplete(DriveFileError error);
// Part of Load().
// This function should be called when the directory load is complete.
// Flushes the callbacks waiting for the directory to be loaded.
void OnDirectoryLoadComplete(const DirectoryFetchInfo& directory_fetch_info,
DriveFileError error);
// ================= Implementation for change list loading =================
// Initiates the change list loading from the server when |local_changestamp| // Initiates the change list loading from the server when |local_changestamp|
// is older than the server changestamp. If |directory_fetch_info| is set, // is older than the server changestamp. If |directory_fetch_info| is set,
// do directory loading before change list loading. // do directory loading before change list loading.
void LoadFromServerIfNeeded(const DirectoryFetchInfo& directory_fetch_info, void LoadFromServerIfNeeded(const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp); int64 local_changestamp);
// Part of Load(). // Part of LoadFromServerIfNeeded().
// Checks the directory's changestamp and |last_known_remote_changestamp_|, // Called after GetAboutResource() for getting remote changestamp is complete.
// and load the feed from server if it is old. Runs |callback| when it's done. void LoadFromServerIfNeededAfterGetAbout(
void CheckChangestampAndLoadDirectoryIfNeeed(
const DirectoryFetchInfo& directory_fetch_info, const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp, int64 local_changestamp,
const FileOperationCallback& callback); google_apis::GDataErrorCode status,
scoped_ptr<google_apis::AboutResource> about_resource);
// Part of LoadFromServerIfNeeded().
// When LoadFromServerIfNeeded is called with |directory_fetch_info| for a
// specific directory, it tries to load the directory before loading the
// content of full filesystem. This method is called after directory loading
// is finished, and proceeds to the normal pass: LoadChangeListServer.
void LoadChangeListFromServerAfterLoadDirectory(
const DirectoryFetchInfo& directory_fetch_info,
scoped_ptr<google_apis::AboutResource> about_resource,
int64 start_changestamp,
DriveFileError error);
// Part of LoadFromServerIfNeeded().
// Starts loading the change list since |start_changestamp|, or the full
// resource list if |start_changestamp| is zero. For full update, the
// largest_change_id and root_folder_id from |about_resource| will be used.
void LoadChangeListFromServer(
scoped_ptr<google_apis::AboutResource> about_resource,
int64 start_changestamp);
// Part of LoadChangeListFromServer(). // Part of LoadFromServerIfNeeded().
// Callback to fetch all the resource list response from the server. // Callback to fetch all the resource list response from the server.
// After all the resource list are fetched, |callback| // After all the resource list are fetched, |callback|
// will be invoked with the collected change lists. // will be invoked with the collected change lists.
// |callback| must not be null. void OnGetResourceList(ScopedVector<ChangeList> change_lists,
void OnGetResourceList( const LoadFeedListCallback& callback,
base::TimeTicks start_time,
google_apis::GDataErrorCode status,
scoped_ptr<google_apis::ResourceList> data);
// Part of LoadFromServerIfNeeded().
// Applies the change list loaded from the server to local metadata storage.
void UpdateMetadataFromFeedAfterLoadFromServer(
scoped_ptr<google_apis::AboutResource> about_resource,
bool is_delta_feed,
ScopedVector<ChangeList> change_lists, ScopedVector<ChangeList> change_lists,
const LoadFeedListCallback& callback, DriveFileError error);
base::TimeTicks start_time,
google_apis::GDataErrorCode status, // Part of LoadFromServerIfNeeded().
scoped_ptr<google_apis::ResourceList> data); // Called when UpdateMetadataFromFeedAfterLoadFromServer is finished.
void OnUpdateFromFeed();
// Part of LoadDirectoryFromServer(). Called when // ================= Implementation for directory loading =================
// DriveScheduler::GetAboutResource() is complete. Calls
// DoLoadDirectoryFromServer() to initiate the directory contents loading. // Part of LoadDirectoryFromServer().
// Called after GetAboutResource() for getting remote changestamp is complete.
// Note that it directly proceeds to DoLoadDirectoryFromServer() not going
// through CheckChangestampAndLoadDirectoryIfNeeed, because the purpose of
// LoadDirectoryFromServer is to force reloading regardless of changestamp.
void LoadDirectoryFromServerAfterGetAbout( void LoadDirectoryFromServerAfterGetAbout(
const std::string& directory_resource_id, const std::string& directory_resource_id,
const FileOperationCallback& callback, const FileOperationCallback& callback,
google_apis::GDataErrorCode status, google_apis::GDataErrorCode status,
scoped_ptr<google_apis::AboutResource> about_resource); scoped_ptr<google_apis::AboutResource> about_resource);
// Initiates the directory contents loading, based on |directory_fetch_info|. // Compares the directory's changestamp and |last_known_remote_changestamp_|.
// When it is finished it just runs |callback| but no other callbacks in // Starts DoLoadDirectoryFromServer() if the local data is old and runs
// |pending_load_callback_|, because it depends on the caller whether to flush // |callback| when finished. If it is up to date, calls back immediately.
// callbacks. Thus, the caller must be responsible for task flushing. void CheckChangestampAndLoadDirectoryIfNeeed(
const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp,
const FileOperationCallback& callback);
// Loads the directory contents from server, and updates the local metadata.
// Runs |callback| when it is finished.
void DoLoadDirectoryFromServer(const DirectoryFetchInfo& directory_fetch_info, void DoLoadDirectoryFromServer(const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback); const FileOperationCallback& callback);
// Part of DoLoadDirectoryFromServer for the grand root ("/drive" directory). // Part of DoLoadDirectoryFromServer() for the grand root ("/drive").
// Called when GetEntryInfoByPath is completed.
// |callback| must not be null.
void DoLoadGrandRootDirectoryFromServerAfterGetEntryInfoByPath( void DoLoadGrandRootDirectoryFromServerAfterGetEntryInfoByPath(
const DirectoryFetchInfo& directory_fetch_info, const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback, const FileOperationCallback& callback,
DriveFileError error, DriveFileError error,
scoped_ptr<DriveEntryProto> entry_proto); scoped_ptr<DriveEntryProto> entry_proto);
// Part of DoLoadDirectoryFromServer for the grand root ("/drive" directory). // Part of DoLoadDirectoryFromServer() for the grand root ("/drive").
// Called when GetAboutResource is completed.
// |callback| must not be null.
void DoLoadGrandRootDirectoryFromServerAfterGetAboutResource( void DoLoadGrandRootDirectoryFromServerAfterGetAboutResource(
const DirectoryFetchInfo& directory_fetch_info, const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback, const FileOperationCallback& callback,
google_apis::GDataErrorCode status, google_apis::GDataErrorCode status,
scoped_ptr<google_apis::AboutResource> about_resource); scoped_ptr<google_apis::AboutResource> about_resource);
// Part of DoLoadDirectoryFromServer(). Called after // Part of DoLoadDirectoryFromServer() for a normal directory.
// LoadFromServer() is complete.
void DoLoadDirectoryFromServerAfterLoad( void DoLoadDirectoryFromServerAfterLoad(
const DirectoryFetchInfo& directory_fetch_info, const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback, const FileOperationCallback& callback,
ScopedVector<ChangeList> change_lists, ScopedVector<ChangeList> change_lists,
DriveFileError error); DriveFileError error);
// Part of DoLoadDirectoryFromServer(). Called after // Part of DoLoadDirectoryFromServer().
// DriveResourceMetadata::RefreshDirectory() is complete.
void DoLoadDirectoryFromServerAfterRefresh( void DoLoadDirectoryFromServerAfterRefresh(
const DirectoryFetchInfo& directory_fetch_info, const DirectoryFetchInfo& directory_fetch_info,
const FileOperationCallback& callback, const FileOperationCallback& callback,
DriveFileError error, DriveFileError error,
const base::FilePath& directory_path); const base::FilePath& directory_path);
// Part of LoadFromServerIfNeeded(). Called when GetAboutResource is complete. // ================= Implementation for other stuff =================
void LoadFromServerIfNeededAfterGetAbout(
const DirectoryFetchInfo& directory_fetch_info,
int64 local_changestamp,
google_apis::GDataErrorCode status,
scoped_ptr<google_apis::AboutResource> about_resource);
// Part of LoadFromServerIfNeeded().
// Starts loading the change list since |start_changestamp|, or the full
// resource list if |start_changestamp| is zero. For full update, the
// largest_change_id and root_folder_id from |about_resource| will be used.
void LoadChangeListFromServer(
scoped_ptr<google_apis::AboutResource> about_resource,
int64 start_changestamp);
// Part of LoadFromServerIfNeeded().
// Starts loading the change list from the server. Called after the
// directory contents are "fast-fetch"ed.
void LoadChangeListFromServerAfterLoadDirectory(
const DirectoryFetchInfo& directory_fetch_info,
scoped_ptr<google_apis::AboutResource> about_resource,
int64 start_changestamp,
DriveFileError error);
// Callback for handling response from |DriveAPIService::GetAppList|. // Callback for handling response from |DriveAPIService::GetAppList|.
// If the application list is successfully parsed, passes the list to // If the application list is successfully parsed, passes the list to
...@@ -231,39 +254,17 @@ class ChangeListLoader { ...@@ -231,39 +254,17 @@ class ChangeListLoader {
void OnGetAppList(google_apis::GDataErrorCode status, void OnGetAppList(google_apis::GDataErrorCode status,
scoped_ptr<google_apis::AppList> app_list); scoped_ptr<google_apis::AppList> app_list);
// Part of SearchFromServer. Called when ResourceList is fetched from the // Part of SearchFromServer().
// server. // Processes the ResourceList received from server and passes to |callback|.
// |callback| must not be null.
void SearchFromServerAfterGetResourceList( void SearchFromServerAfterGetResourceList(
const LoadFeedListCallback& callback, const LoadFeedListCallback& callback,
google_apis::GDataErrorCode status, google_apis::GDataErrorCode status,
scoped_ptr<google_apis::ResourceList> resource_list); scoped_ptr<google_apis::ResourceList> resource_list);
// Part of LoadChangeListFromServer(). // Part of UpdateFromFeed().
// Applies the change list loaded from the server to local metadata storage.
void UpdateMetadataFromFeedAfterLoadFromServer(
scoped_ptr<google_apis::AboutResource> about_resource,
bool is_delta_feed,
ScopedVector<ChangeList> change_lists,
DriveFileError error);
// Callback for ChangeListProcessor::ApplyFeeds. // Callback for ChangeListProcessor::ApplyFeeds.
void NotifyDirectoryChangedAfterApplyFeed( void NotifyDirectoryChangedAfterApplyFeed(bool should_notify,
bool should_notify, const base::Closure& callback);
const base::Closure& update_finished_callback);
// Part of LoadChangeListFromServer().
// Called when UpdateMetadataFromFeedAfterLoadFromServer is finished.
void OnUpdateFromFeed();
// This function should be called when the change list load is complete.
// Flushes the callbacks for change list loading and all directory loading.
void OnChangeListLoadComplete(DriveFileError error);
// This function should be called when the directory load is complete.
// Flushes the callbacks waiting for the directory to be loaded.
void OnDirectoryLoadComplete(const DirectoryFetchInfo& directory_fetch_info,
DriveFileError error);
DriveResourceMetadata* resource_metadata_; // Not owned. DriveResourceMetadata* resource_metadata_; // Not owned.
DriveScheduler* scheduler_; // Not owned. DriveScheduler* scheduler_; // Not owned.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment