| Index: chrome/browser/chromeos/gdata/gdata_file_system.cc
|
| diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.cc b/chrome/browser/chromeos/gdata/gdata_file_system.cc
|
| index 949ca502c72fbfceca97db5ae5b43830ffc99bac..4884f1e38f8bf705b8a3e86462c59da984242874 100644
|
| --- a/chrome/browser/chromeos/gdata/gdata_file_system.cc
|
| +++ b/chrome/browser/chromeos/gdata/gdata_file_system.cc
|
| @@ -55,6 +55,9 @@ const int kGDataUpdateCheckIntervalInSec = 5;
|
| const int kGDataUpdateCheckIntervalInSec = 60;
|
| #endif
|
|
|
| +// Update the fetch progress UI per every this number of feeds.
|
| +const int kFetchUiUpdateStep = 10;
|
| +
|
| // Schedule for dumping root file system proto buffers to disk depending its
|
| // total protobuffer size in MB.
|
| typedef struct {
|
| @@ -585,6 +588,36 @@ void GDataWapiFeedLoader::RemoveObserver(Observer* observer) {
|
| observers_.RemoveObserver(observer);
|
| }
|
|
|
| +// Defines set of parameters sent to callback OnNotifyDocumentFeedFetched().
|
| +// This is a trick to update the number of fetched documents frequently on
|
| +// UI. Due to performance reason, we need to fetch a number of files at
|
| +// a time. However, it'll take long time, and a user has no way to know
|
| +// the current update state. In order to make users confortable,
|
| +// we increment the number of fetched documents with more frequent but smaller
|
| +// steps than actual fetching.
|
| +struct GetDocumentsUiState {
|
| + explicit GetDocumentsUiState(base::TimeTicks start_time)
|
| + : num_fetched_documents(0),
|
| + num_showing_documents(0),
|
| + start_time(start_time),
|
| + weak_ptr_factory(this) {
|
| + }
|
| +
|
| + // The number of fetched documents.
|
| + int num_fetched_documents;
|
| +
|
| + // The number documents shown on UI.
|
| + int num_showing_documents;
|
| +
|
| + // When the UI update has started.
|
| + base::TimeTicks start_time;
|
| +
|
| + // Time elapsed since the feed fetching was started.
|
| + base::TimeDelta feed_fetching_elapsed_time;
|
| +
|
| + base::WeakPtrFactory<GetDocumentsUiState> weak_ptr_factory;
|
| +};
|
| +
|
| // Defines set of parameters sent to callback OnGetDocuments().
|
| // TODO(satorux): Move this to a new file: crbug.com/138268
|
| struct GetDocumentsParams {
|
| @@ -595,7 +628,8 @@ struct GetDocumentsParams {
|
| const FilePath& search_file_path,
|
| const std::string& search_query,
|
| const std::string& directory_resource_id,
|
| - const FindEntryCallback& callback);
|
| + const FindEntryCallback& callback,
|
| + GetDocumentsUiState* ui_state);
|
| ~GetDocumentsParams();
|
|
|
| // Changestamps are positive numbers in increasing order. The difference
|
| @@ -612,6 +646,7 @@ struct GetDocumentsParams {
|
| std::string search_query;
|
| std::string directory_resource_id;
|
| FindEntryCallback callback;
|
| + scoped_ptr<GetDocumentsUiState> ui_state;
|
| };
|
|
|
| GetDocumentsParams::GetDocumentsParams(
|
| @@ -622,7 +657,8 @@ GetDocumentsParams::GetDocumentsParams(
|
| const FilePath& search_file_path,
|
| const std::string& search_query,
|
| const std::string& directory_resource_id,
|
| - const FindEntryCallback& callback)
|
| + const FindEntryCallback& callback,
|
| + GetDocumentsUiState* ui_state)
|
| : start_changestamp(start_changestamp),
|
| root_feed_changestamp(root_feed_changestamp),
|
| feed_list(feed_list),
|
| @@ -630,7 +666,8 @@ GetDocumentsParams::GetDocumentsParams(
|
| search_file_path(search_file_path),
|
| search_query(search_query),
|
| directory_resource_id(directory_resource_id),
|
| - callback(callback) {
|
| + callback(callback),
|
| + ui_state(ui_state) {
|
| }
|
|
|
| GetDocumentsParams::~GetDocumentsParams() {
|
| @@ -1086,7 +1123,8 @@ void GDataWapiFeedLoader::LoadFromServer(
|
| search_file_path,
|
| search_query,
|
| directory_resource_id,
|
| - entry_found_callback)),
|
| + entry_found_callback,
|
| + NULL)),
|
| start_time));
|
| }
|
|
|
| @@ -2834,13 +2872,29 @@ void GDataWapiFeedLoader::OnGetDocuments(
|
| for (size_t i = 0; i < params->feed_list->size(); ++i)
|
| num_accumulated_entries += params->feed_list->at(i)->entries().size();
|
|
|
| - // Notify the observers that a document feed is fetched.
|
| - FOR_EACH_OBSERVER(Observer, observers_,
|
| - OnDocumentFeedFetched(num_accumulated_entries));
|
| -
|
| // Check if we need to collect more data to complete the directory list.
|
| if (params->should_fetch_multiple_feeds && has_next_feed_url &&
|
| !next_feed_url.is_empty()) {
|
| + // Post an UI update event to make the UI smoother.
|
| + GetDocumentsUiState* ui_state = params->ui_state.get();
|
| + if (ui_state == NULL) {
|
| + ui_state = new GetDocumentsUiState(base::TimeTicks::Now());
|
| + params->ui_state.reset(ui_state);
|
| + }
|
| + DCHECK(ui_state);
|
| +
|
| + if ((ui_state->num_fetched_documents - ui_state->num_showing_documents)
|
| + < kFetchUiUpdateStep) {
|
| + // Currently the UI update is stopped. Start UI periodic callback.
|
| + MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GDataWapiFeedLoader::OnNotifyDocumentFeedFetched,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + ui_state->weak_ptr_factory.GetWeakPtr()));
|
| + }
|
| + ui_state->num_fetched_documents = num_accumulated_entries;
|
| + ui_state->feed_fetching_elapsed_time = base::TimeTicks::Now() - start_time;
|
| +
|
| // Kick of the remaining part of the feeds.
|
| documents_service_->GetDocuments(
|
| next_feed_url,
|
| @@ -2860,11 +2914,16 @@ void GDataWapiFeedLoader::OnGetDocuments(
|
| params->search_file_path,
|
| params->search_query,
|
| params->directory_resource_id,
|
| - params->callback)),
|
| + params->callback,
|
| + params->ui_state.release())),
|
| start_time));
|
| return;
|
| }
|
|
|
| + // Notify the observers that a document feed is fetched.
|
| + FOR_EACH_OBSERVER(Observer, observers_,
|
| + OnDocumentFeedFetched(num_accumulated_entries));
|
| +
|
| UMA_HISTOGRAM_TIMES("Gdata.EntireFeedLoadTime",
|
| base::TimeTicks::Now() - start_time);
|
|
|
| @@ -2872,6 +2931,43 @@ void GDataWapiFeedLoader::OnGetDocuments(
|
| callback.Run(params, error);
|
| }
|
|
|
| +void GDataWapiFeedLoader::OnNotifyDocumentFeedFetched(
|
| + base::WeakPtr<GetDocumentsUiState> ui_state) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + if (!ui_state) {
|
| + // The ui state instance is already released, which means the fetching
|
| + // is done and we don't need to update any more.
|
| + return;
|
| + }
|
| +
|
| + base::TimeDelta elapsed_time =
|
| + base::TimeTicks::Now() - ui_state->start_time;
|
| +
|
| + if (ui_state->num_showing_documents + kFetchUiUpdateStep <=
|
| + ui_state->num_fetched_documents) {
|
| + ui_state->num_showing_documents += kFetchUiUpdateStep;
|
| + FOR_EACH_OBSERVER(Observer, observers_,
|
| + OnDocumentFeedFetched(ui_state->num_showing_documents));
|
| +
|
| + int num_remaining_ui_updates =
|
| + (ui_state->num_fetched_documents - ui_state->num_showing_documents)
|
| + / kFetchUiUpdateStep;
|
| + if (num_remaining_ui_updates > 0) {
|
| + // Heuristically, we use fetched time duration to calculate the next
|
| + // UI update timing.
|
| + base::TimeDelta remaining_duration =
|
| + ui_state->feed_fetching_elapsed_time - elapsed_time;
|
| + MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&GDataWapiFeedLoader::OnNotifyDocumentFeedFetched,
|
| + weak_ptr_factory_.GetWeakPtr(),
|
| + ui_state->weak_ptr_factory.GetWeakPtr()),
|
| + remaining_duration / num_remaining_ui_updates);
|
| + }
|
| + }
|
| +}
|
| +
|
| void GDataWapiFeedLoader::LoadFromCache(
|
| bool should_load_from_server,
|
| const FilePath& search_file_path,
|
|
|