Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / history / in_memory_history_backend.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/history/in_memory_history_backend.h"
6
7 #include <set>
8 #include <vector>
9
10 #include "base/command_line.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/time/time.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/history/history_notifications.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "components/history/core/browser/in_memory_database.h"
18 #include "components/history/core/browser/url_database.h"
19 #include "content/public/browser/notification_details.h"
20 #include "content/public/browser/notification_source.h"
21
22 namespace history {
23
24 InMemoryHistoryBackend::InMemoryHistoryBackend()
25     : profile_(NULL) {
26 }
27
28 InMemoryHistoryBackend::~InMemoryHistoryBackend() {}
29
30 bool InMemoryHistoryBackend::Init(const base::FilePath& history_filename) {
31   db_.reset(new InMemoryDatabase);
32   return db_->InitFromDisk(history_filename);
33 }
34
35 void InMemoryHistoryBackend::AttachToHistoryService(Profile* profile) {
36   if (!db_) {
37     NOTREACHED();
38     return;
39   }
40
41   profile_ = profile;
42
43   // TODO(evanm): this is currently necessitated by generate_profile, which
44   // runs without a browser process. generate_profile should really create
45   // a browser process, at which point this check can then be nuked.
46   if (!g_browser_process)
47     return;
48
49   // Register for the notifications we care about.
50   // We only want notifications for the associated profile.
51   content::Source<Profile> source(profile_);
52   registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source);
53   registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, source);
54   registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
55   registrar_.Add(
56       this, chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, source);
57   registrar_.Add(
58       this, chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, source);
59 }
60
61 void InMemoryHistoryBackend::DeleteAllSearchTermsForKeyword(
62     KeywordID keyword_id) {
63   // For simplicity, this will not remove the corresponding URLRows, but
64   // this is okay, as the main database does not do so either.
65   db_->DeleteAllSearchTermsForKeyword(keyword_id);
66 }
67
68 void InMemoryHistoryBackend::Observe(
69     int type,
70     const content::NotificationSource& source,
71     const content::NotificationDetails& details) {
72   switch (type) {
73     case chrome::NOTIFICATION_HISTORY_URL_VISITED:
74       OnURLVisitedOrModified(content::Details<URLVisitedDetails>(details)->row);
75       break;
76     case chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED:
77       OnKeywordSearchTermUpdated(
78           *content::Details<KeywordSearchUpdatedDetails>(details).ptr());
79       break;
80     case chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED:
81       OnKeywordSearchTermDeleted(
82           *content::Details<KeywordSearchDeletedDetails>(details).ptr());
83       break;
84     case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED: {
85       const URLsModifiedDetails* modified_details =
86           content::Details<URLsModifiedDetails>(details).ptr();
87       URLRows::const_iterator it;
88       for (it = modified_details->changed_urls.begin();
89            it != modified_details->changed_urls.end(); ++it) {
90         OnURLVisitedOrModified(*it);
91       }
92       break;
93     }
94     case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
95       OnURLsDeleted(*content::Details<URLsDeletedDetails>(details).ptr());
96       break;
97     default:
98       // For simplicity, the unit tests send us all notifications, even when
99       // we haven't registered for them, so don't assert here.
100       break;
101   }
102 }
103
104 void InMemoryHistoryBackend::OnURLVisitedOrModified(const URLRow& url_row) {
105   DCHECK(db_);
106   DCHECK(url_row.id());
107   if (url_row.typed_count() || db_->GetKeywordSearchTermRow(url_row.id(), NULL))
108     db_->InsertOrUpdateURLRowByID(url_row);
109   else
110     db_->DeleteURLRow(url_row.id());
111 }
112
113 void InMemoryHistoryBackend::OnURLsDeleted(const URLsDeletedDetails& details) {
114   DCHECK(db_);
115
116   if (details.all_history) {
117     // When all history is deleted, the individual URLs won't be listed. Just
118     // create a new database to quickly clear everything out.
119     db_.reset(new InMemoryDatabase);
120     if (!db_->InitFromScratch())
121       db_.reset();
122     return;
123   }
124
125   // Delete all matching URLs in our database.
126   for (URLRows::const_iterator row = details.rows.begin();
127        row != details.rows.end(); ++row) {
128     // This will also delete the corresponding keyword search term.
129     // Ignore errors, as we typically only cache a subset of URLRows.
130     db_->DeleteURLRow(row->id());
131   }
132 }
133
134 void InMemoryHistoryBackend::OnKeywordSearchTermUpdated(
135     const KeywordSearchUpdatedDetails& details) {
136   DCHECK(details.url_row.id());
137   db_->InsertOrUpdateURLRowByID(details.url_row);
138   db_->SetKeywordSearchTermsForURL(
139       details.url_row.id(), details.keyword_id, details.term);
140 }
141
142 void InMemoryHistoryBackend::OnKeywordSearchTermDeleted(
143     const KeywordSearchDeletedDetails& details) {
144   // For simplicity, this will not remove the corresponding URLRow, but this is
145   // okay, as the main database does not do so either.
146   db_->DeleteKeywordSearchTermForURL(details.url_row_id);
147 }
148
149 }  // namespace history