Index: chrome/browser/android/history_report/data_provider.cc |
diff --git a/chrome/browser/android/history_report/data_provider.cc b/chrome/browser/android/history_report/data_provider.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e2892793b5bb297109789657993f1463dbff04bc |
--- /dev/null |
+++ b/chrome/browser/android/history_report/data_provider.cc |
@@ -0,0 +1,193 @@ |
+// Copyright 2015 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/android/history_report/data_provider.h" |
+#include "base/bind.h" |
+#include "base/containers/hash_tables.h" |
+#include "base/logging.h" |
+#include "base/synchronization/waitable_event.h" |
+#include "chrome/browser/android/history_report/delta_file_commons.h" |
+#include "chrome/browser/android/history_report/delta_file_service.h" |
+#include "chrome/browser/android/history_report/get_all_urls_from_history_task.h" |
+#include "chrome/browser/android/history_report/historic_visits_migration_task.h" |
+#include "chrome/browser/android/history_report/usage_reports_buffer_service.h" |
+#include "chrome/browser/history/history_service_factory.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "components/bookmarks/browser/bookmark_model.h" |
+#include "components/history/core/browser/history_db_task.h" |
+#include "components/history/core/browser/history_service.h" |
+#include "content/public/browser/browser_thread.h" |
+ |
+using bookmarks::BookmarkModel; |
+ |
+namespace { |
+typedef base::hash_map<std::string, BookmarkModel::URLAndTitle*> BookmarkMap; |
+ |
+struct Context { |
+ history::HistoryService* history_service; |
+ base::CancelableTaskTracker* history_task_tracker; |
+ base::WaitableEvent finished; |
+ |
+ Context(history::HistoryService* hservice, |
+ base::CancelableTaskTracker* tracker) |
+ : history_service(hservice), |
+ history_task_tracker(tracker), |
+ finished(false, false) {} |
+}; |
+ |
+void UpdateUrl(Context* context, |
+ size_t position, |
+ std::vector<history_report::DeltaFileEntryWithData>* urls, |
+ bool success, |
+ const history::URLRow& url, |
+ const history::VisitVector& visits) { |
+ history_report::DeltaFileEntryWithData* entry = &((*urls)[position]); |
+ if (success) { |
+ entry->SetData(url); |
+ } else { |
+ LOG(WARNING) << "No data for url " << entry->Url(); |
+ } |
+ if (position + 1 == urls->size()) { |
+ context->finished.Signal(); |
+ } else { |
+ context->history_service->QueryURL(GURL((*urls)[position + 1].Url()), |
+ false, |
+ base::Bind(&UpdateUrl, |
+ base::Unretained(context), |
+ position + 1, |
+ base::Unretained(urls)), |
+ context->history_task_tracker); |
+ } |
+} |
+ |
+void QueryUrlsHistoryInUiThread( |
+ Context* context, |
+ std::vector<history_report::DeltaFileEntryWithData>* urls) { |
+ context->history_task_tracker->TryCancelAll(); |
+ // TODO(haaawk): change history service so that all this data can be |
+ // obtained with a single call to history service. |
+ context->history_service->QueryURL(GURL((*urls)[0].Url()), |
+ false, |
+ base::Bind(&UpdateUrl, |
+ base::Unretained(context), |
+ 0, |
+ base::Unretained(urls)), |
+ context->history_task_tracker); |
+} |
+ |
+void StartVisitMigrationToUsageBufferUiThread( |
+ history::HistoryService* history_service, |
+ history_report::UsageReportsBufferService* buffer_service, |
+ base::WaitableEvent* finished, |
+ base::CancelableTaskTracker* task_tracker) { |
+ history_service->ScheduleDBTask( |
+ scoped_ptr<history::HistoryDBTask>( |
+ new history_report::HistoricVisitsMigrationTask(finished, |
+ buffer_service)), |
+ task_tracker); |
+} |
+ |
+} // namespace |
+ |
+namespace history_report { |
+ |
+DataProvider::DataProvider(Profile* profile, |
+ DeltaFileService* delta_file_service, |
+ BookmarkModel* bookmark_model) |
+ : bookmark_model_(bookmark_model), |
+ delta_file_service_(delta_file_service) { |
+ history_service_ = HistoryServiceFactory::GetForProfile( |
+ profile, ServiceAccessType::EXPLICIT_ACCESS); |
+} |
+ |
+DataProvider::~DataProvider() {} |
+ |
+scoped_ptr<std::vector<DeltaFileEntryWithData> > DataProvider::Query( |
+ int64 last_seq_no, |
+ int32 limit) { |
+ if (last_seq_no == 0) |
+ RecreateLog(); |
+ scoped_ptr<std::vector<DeltaFileEntryWithData> > entries; |
+ scoped_ptr<std::vector<DeltaFileEntryWithData> > valid_entries; |
+ do { |
+ entries = delta_file_service_->Query(last_seq_no, limit); |
+ if (!entries->empty()) { |
+ Context context(history_service_, |
+ &history_task_tracker_); |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&QueryUrlsHistoryInUiThread, |
+ base::Unretained(&context), |
+ base::Unretained(entries.get()))); |
+ std::vector<BookmarkModel::URLAndTitle> bookmarks; |
+ bookmark_model_->BlockTillLoaded(); |
+ bookmark_model_->GetBookmarks(&bookmarks); |
+ BookmarkMap bookmark_map; |
+ for (size_t i = 0; i < bookmarks.size(); ++i) { |
+ bookmark_map.insert( |
+ make_pair(bookmarks[i].url.spec(), &bookmarks[i])); |
+ } |
+ context.finished.Wait(); |
+ for (size_t i = 0; i < entries->size(); ++i) { |
+ BookmarkMap::iterator bookmark = |
+ bookmark_map.find((*entries)[i].Url()); |
+ if (bookmark != bookmark_map.end()) |
+ (*entries)[i].MarkAsBookmark(*(bookmark->second)); |
+ } |
+ } |
+ |
+ valid_entries.reset(new std::vector<DeltaFileEntryWithData>()); |
+ valid_entries->reserve(entries->size()); |
+ for (size_t i = 0; i < entries->size(); ++i) { |
+ const DeltaFileEntryWithData& entry = (*entries)[i]; |
+ if (entry.Valid()) valid_entries->push_back(entry); |
+ if (entry.SeqNo() > last_seq_no) last_seq_no = entry.SeqNo(); |
+ } |
+ } while (!entries->empty() && valid_entries->empty()); |
+ return valid_entries.Pass(); |
+} |
+ |
+void DataProvider::StartVisitMigrationToUsageBuffer( |
+ UsageReportsBufferService* buffer_service) { |
+ base::WaitableEvent finished(false, false); |
+ buffer_service->Clear(); |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&StartVisitMigrationToUsageBufferUiThread, |
+ base::Unretained(history_service_), |
+ buffer_service, |
+ base::Unretained(&finished), |
+ base::Unretained(&history_task_tracker_))); |
+ finished.Wait(); |
+} |
+ |
+void DataProvider::RecreateLog() { |
+ std::vector<std::string> urls; |
+ { |
+ base::WaitableEvent finished(false, false); |
+ |
+ scoped_ptr<history::HistoryDBTask> task = |
+ scoped_ptr<history::HistoryDBTask>(new GetAllUrlsFromHistoryTask( |
+ &finished, &urls)); |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::UI, FROM_HERE, |
+ base::Bind(base::IgnoreResult(&history::HistoryService::ScheduleDBTask), |
+ base::Unretained(history_service_), base::Passed(&task), |
+ base::Unretained(&history_task_tracker_))); |
+ finished.Wait(); |
+ } |
+ |
+ std::vector<BookmarkModel::URLAndTitle> bookmarks; |
+ bookmark_model_->BlockTillLoaded(); |
+ bookmark_model_->GetBookmarks(&bookmarks); |
+ urls.reserve(urls.size() + bookmarks.size()); |
+ for (size_t i = 0; i < bookmarks.size(); i++) { |
+ urls.push_back(bookmarks[i].url.spec()); |
+ } |
+ delta_file_service_->Recreate(urls); |
+} |
+ |
+} // namespace history_report |