15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/in_memory_url_index.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/trace_event.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h"
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_notifications.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/url_index_private_data.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_model.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/history/core/browser/url_database.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using in_memory_url_index::InMemoryURLIndexCacheItem;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called by DoSaveToCacheFile to delete any old cache file at |path| when
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// there is no private data to save. Runs on the FILE thread.
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeleteCacheFile(const base::FilePath& path) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::DeleteFile(path, false);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initializes a whitelist of URL schemes.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitializeSchemeWhitelist(std::set<std::string>* whitelist) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(whitelist);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!whitelist->empty())
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Nothing to do, already initialized.
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  whitelist->insert(std::string(url::kAboutScheme));
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  whitelist->insert(std::string(content::kChromeUIScheme));
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  whitelist->insert(std::string(url::kFileScheme));
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  whitelist->insert(std::string(url::kFtpScheme));
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  whitelist->insert(std::string(url::kHttpScheme));
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  whitelist->insert(std::string(url::kHttpsScheme));
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  whitelist->insert(std::string(url::kMailToScheme));
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Restore/SaveCacheObserver ---------------------------------------------------
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InMemoryURLIndex::RestoreCacheObserver::~RestoreCacheObserver() {}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InMemoryURLIndex::SaveCacheObserver::~SaveCacheObserver() {}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RebuildPrivateDataFromHistoryDBTask -----------------------------------------
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RebuildPrivateDataFromHistoryDBTask(
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        InMemoryURLIndex* index,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::string& languages,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::set<std::string>& scheme_whitelist)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : index_(index),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      languages_(languages),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scheme_whitelist_(scheme_whitelist),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      succeeded_(false) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::RunOnDBThread(
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HistoryBackend* backend,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HistoryDatabase* db) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_ = URLIndexPrivateData::RebuildFromHistory(db, languages_,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  scheme_whitelist_);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  succeeded_ = data_.get() && !data_->Empty();
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!succeeded_ && data_.get())
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_->Clear();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneRunOnMainThread() {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  index_->DoneRebuidingPrivateDataFromHistoryDB(succeeded_, data_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask::
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~RebuildPrivateDataFromHistoryDBTask() {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InMemoryURLIndex ------------------------------------------------------------
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InMemoryURLIndex::InMemoryURLIndex(Profile* profile,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const base::FilePath& history_dir,
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                   const std::string& languages,
9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                   HistoryClient* history_client)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(profile),
9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      history_client_(history_client),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      history_dir_(history_dir),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      languages_(languages),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      private_data_(new URLIndexPrivateData),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restore_cache_observer_(NULL),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_cache_observer_(NULL),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shutdown_(false),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restored_(false),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      needs_to_be_cached_(false) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeSchemeWhitelist(&scheme_whitelist_);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (profile) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(mrossetti): Register for language change notifications.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::Source<Profile> source(profile);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   source);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called only by unit tests.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InMemoryURLIndex::InMemoryURLIndex()
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : profile_(NULL),
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      history_client_(NULL),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      private_data_(new URLIndexPrivateData),
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restore_cache_observer_(NULL),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_cache_observer_(NULL),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shutdown_(false),
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restored_(false),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      needs_to_be_cached_(false) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeSchemeWhitelist(&scheme_whitelist_);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InMemoryURLIndex::~InMemoryURLIndex() {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there was a history directory (which there won't be for some unit tests)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // then insure that the cache has already been saved.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(history_dir_.empty() || !needs_to_be_cached_);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::Init() {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostRestoreFromCacheFileTask();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::ShutDown() {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.RemoveAll();
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  cache_reader_tracker_.TryCancelAll();
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shutdown_ = true;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetCacheFilePath(&path))
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  private_data_tracker_.TryCancelAll();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLIndexPrivateData::WritePrivateDataToCacheFileTask(private_data_, path);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  needs_to_be_cached_ = false;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::ClearPrivateData() {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private_data_->Clear();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool InMemoryURLIndex::GetCacheFilePath(base::FilePath* file_path) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (history_dir_.empty())
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *file_path = history_dir_.Append(FILE_PATH_LITERAL("History Provider Cache"));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Querying --------------------------------------------------------------------
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScoredHistoryMatches InMemoryURLIndex::HistoryItemsForTerms(
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& term_string,
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t cursor_position,
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t max_matches) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return private_data_->HistoryItemsForTerms(
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      term_string,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cursor_position,
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      max_matches,
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      languages_,
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      history_client_);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Updating --------------------------------------------------------------------
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::DeleteURL(const GURL& url) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private_data_->DeleteURL(url);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::Observe(int notification_type,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const content::NotificationSource& source,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const content::NotificationDetails& details) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (notification_type) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_HISTORY_URL_VISITED:
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnURLVisited(content::Details<URLVisitedDetails>(details).ptr());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnURLsModified(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Details<history::URLsModifiedDetails>(details).ptr());
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnURLsDeleted(
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Details<history::URLsDeletedDetails>(details).ptr());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_HISTORY_LOADED:
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      registrar_.Remove(this, chrome::NOTIFICATION_HISTORY_LOADED,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        content::Source<Profile>(profile_));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScheduleRebuildFromHistory();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // For simplicity, the unit tests send us all notifications, even when
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // we haven't registered for them, so don't assert here.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::OnURLVisited(const URLVisitedDetails* details) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HistoryService* service =
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      HistoryServiceFactory::GetForProfile(profile_,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           Profile::EXPLICIT_ACCESS);
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  needs_to_be_cached_ |= private_data_->UpdateURL(service,
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                  details->row,
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                  languages_,
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                  scheme_whitelist_,
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                  &private_data_tracker_);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::OnURLsModified(const URLsModifiedDetails* details) {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HistoryService* service =
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      HistoryServiceFactory::GetForProfile(profile_,
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           Profile::EXPLICIT_ACCESS);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (URLRows::const_iterator row = details->changed_urls.begin();
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       row != details->changed_urls.end();
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       ++row) {
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    needs_to_be_cached_ |= private_data_->UpdateURL(
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        service, *row, languages_, scheme_whitelist_, &private_data_tracker_);
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::OnURLsDeleted(const URLsDeletedDetails* details) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (details->all_history) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearPrivateData();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    needs_to_be_cached_ = true;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (URLRows::const_iterator row = details->rows.begin();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row != details->rows.end(); ++row)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      needs_to_be_cached_ |= private_data_->DeleteURL(row->url());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // If we made changes, destroy the previous cache.  Otherwise, if we go
2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // through an unclean shutdown (and therefore fail to write a new cache file),
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // when Chrome restarts and we restore from the previous cache, we'll end up
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // searching over URLs that may be deleted.  This would be wrong, and
2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // surprising to the user who bothered to delete some URLs from his/her
2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // history.  In this situation, deleting the cache is a better solution than
2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // writing a new cache (after deleting the URLs from the in-memory structure)
2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // because deleting the cache forces it to be rebuilt from history upon
2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // startup.  If we instead write a new, updated cache then at the time of next
2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // startup (after an unclean shutdown) we will not rebuild the in-memory data
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // structures from history but rather use the cache.  This solution is
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // mediocre because this cache may not have the most-recently-visited URLs
2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // in it (URLs visited after user deleted some URLs from history), which
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // would be odd and confusing.  It's better to force a rebuild.
2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::FilePath path;
2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (needs_to_be_cached_ && GetCacheFilePath(&path)) {
2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    content::BrowserThread::PostBlockingPoolTask(
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        FROM_HERE, base::Bind(DeleteCacheFile, path));
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Restoring from Cache --------------------------------------------------------
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::PostRestoreFromCacheFileTask() {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT0("browser", "InMemoryURLIndex::PostRestoreFromCacheFileTask");
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetCacheFilePath(&path) || shutdown_) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    restored_ = true;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (restore_cache_observer_)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restore_cache_observer_->OnCacheRestoreFinished(false);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::BrowserThread::PostTaskAndReplyWithResult
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      <scoped_refptr<URLIndexPrivateData> >(
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::BrowserThread::FILE, FROM_HERE,
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&URLIndexPrivateData::RestoreFromFile, path, languages_),
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr()));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::OnCacheLoadDone(
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<URLIndexPrivateData> private_data) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (private_data.get() && !private_data->Empty()) {
286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    private_data_tracker_.TryCancelAll();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private_data_ = private_data;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    restored_ = true;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (restore_cache_observer_)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restore_cache_observer_->OnCacheRestoreFinished(true);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (profile_) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When unable to restore from the cache file delete the cache file, if
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // it exists, and then rebuild from the history database if it's available,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // otherwise wait until the history database loaded and then rebuild.
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath path;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetCacheFilePath(&path) || shutdown_)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::BrowserThread::PostBlockingPoolTask(
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE, base::Bind(DeleteCacheFile, path));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HistoryService* service =
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        HistoryServiceFactory::GetForProfileWithoutCreating(profile_);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (service && service->backend_loaded()) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScheduleRebuildFromHistory();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      registrar_.Add(this, chrome::NOTIFICATION_HISTORY_LOADED,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     content::Source<Profile>(profile_));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Restoring from the History DB -----------------------------------------------
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::ScheduleRebuildFromHistory() {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HistoryService* service =
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HistoryServiceFactory::GetForProfile(profile_,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           Profile::EXPLICIT_ACCESS);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  service->ScheduleDBTask(
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scoped_ptr<history::HistoryDBTask>(
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          new InMemoryURLIndex::RebuildPrivateDataFromHistoryDBTask(
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              this, languages_, scheme_whitelist_)),
321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      &cache_reader_tracker_);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::DoneRebuidingPrivateDataFromHistoryDB(
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool succeeded,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<URLIndexPrivateData> private_data) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (succeeded) {
329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    private_data_tracker_.TryCancelAll();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private_data_ = private_data;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PostSaveToCacheFileTask();  // Cache the newly rebuilt index.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private_data_->Clear();  // Dump the old private data.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There is no need to do anything with the cache file as it was deleted
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when the rebuild from the history operation was kicked off.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  restored_ = true;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (restore_cache_observer_)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    restore_cache_observer_->OnCacheRestoreFinished(succeeded);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::RebuildFromHistory(HistoryDatabase* history_db) {
343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  private_data_tracker_.TryCancelAll();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private_data_ = URLIndexPrivateData::RebuildFromHistory(history_db,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          languages_,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          scheme_whitelist_);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Saving to Cache -------------------------------------------------------------
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::PostSaveToCacheFileTask() {
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetCacheFilePath(&path))
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is anything in our private data then make a copy of it and tell
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it to save itself to a file.
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (private_data_.get() && !private_data_->Empty()) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that ownership of the copy of our private data is passed to the
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // completion closure below.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<URLIndexPrivateData> private_data_copy =
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        private_data_->Duplicate();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::BrowserThread::PostTaskAndReplyWithResult<bool>(
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::BrowserThread::FILE, FROM_HERE,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   private_data_copy, path),
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr()));
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there is no data in our index then delete any existing cache file.
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::BrowserThread::PostBlockingPoolTask(
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(DeleteCacheFile, path));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InMemoryURLIndex::OnCacheSaveDone(bool succeeded) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (save_cache_observer_)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    save_cache_observer_->OnCacheSaveFinished(succeeded);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace history
381