Upstream version 11.40.277.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/history/history_service.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "components/history/core/browser/in_memory_database.h"
19 #include "components/history/core/browser/url_database.h"
20 #include "content/public/browser/notification_details.h"
21 #include "content/public/browser/notification_source.h"
22
23 namespace history {
24
25 InMemoryHistoryBackend::InMemoryHistoryBackend()
26     : profile_(nullptr), history_service_(nullptr) {
27 }
28
29 InMemoryHistoryBackend::~InMemoryHistoryBackend() {
30   if (history_service_)
31     history_service_->RemoveObserver(this);
32 }
33
34 bool InMemoryHistoryBackend::Init(const base::FilePath& history_filename) {
35   db_.reset(new InMemoryDatabase);
36   return db_->InitFromDisk(history_filename);
37 }
38
39 void InMemoryHistoryBackend::AttachToHistoryService(
40     Profile* profile,
41     HistoryService* history_service) {
42   if (!db_) {
43     NOTREACHED();
44     return;
45   }
46
47   DCHECK(history_service);
48   history_service_ = history_service;
49   history_service_->AddObserver(this);
50
51   profile_ = profile;
52
53   // TODO(evanm): this is currently necessitated by generate_profile, which
54   // runs without a browser process. generate_profile should really create
55   // a browser process, at which point this check can then be nuked.
56   if (!g_browser_process)
57     return;
58
59   // Register for the notifications we care about.
60   // We only want notifications for the associated profile.
61   content::Source<Profile> source(profile_);
62   registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, source);
63   registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
64   registrar_.Add(
65       this, chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, source);
66   registrar_.Add(
67       this, chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, source);
68 }
69
70 void InMemoryHistoryBackend::DeleteAllSearchTermsForKeyword(
71     KeywordID keyword_id) {
72   // For simplicity, this will not remove the corresponding URLRows, but
73   // this is okay, as the main database does not do so either.
74   db_->DeleteAllSearchTermsForKeyword(keyword_id);
75 }
76
77 void InMemoryHistoryBackend::OnURLVisited(HistoryService* history_service,
78                                           ui::PageTransition transition,
79                                           const URLRow& row,
80                                           const RedirectList& redirects,
81                                           base::Time visit_time) {
82   OnURLVisitedOrModified(row);
83 }
84
85 void InMemoryHistoryBackend::Observe(
86     int type,
87     const content::NotificationSource& source,
88     const content::NotificationDetails& details) {
89   switch (type) {
90     case chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED:
91       OnKeywordSearchTermUpdated(
92           *content::Details<KeywordSearchUpdatedDetails>(details).ptr());
93       break;
94     case chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED:
95       OnKeywordSearchTermDeleted(
96           *content::Details<KeywordSearchDeletedDetails>(details).ptr());
97       break;
98     case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED: {
99       const URLsModifiedDetails* modified_details =
100           content::Details<URLsModifiedDetails>(details).ptr();
101       URLRows::const_iterator it;
102       for (it = modified_details->changed_urls.begin();
103            it != modified_details->changed_urls.end(); ++it) {
104         OnURLVisitedOrModified(*it);
105       }
106       break;
107     }
108     case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
109       OnURLsDeleted(*content::Details<URLsDeletedDetails>(details).ptr());
110       break;
111     default:
112       // For simplicity, the unit tests send us all notifications, even when
113       // we haven't registered for them, so don't assert here.
114       break;
115   }
116 }
117
118 void InMemoryHistoryBackend::OnURLVisitedOrModified(const URLRow& url_row) {
119   DCHECK(db_);
120   DCHECK(url_row.id());
121   if (url_row.typed_count() || db_->GetKeywordSearchTermRow(url_row.id(), NULL))
122     db_->InsertOrUpdateURLRowByID(url_row);
123   else
124     db_->DeleteURLRow(url_row.id());
125 }
126
127 void InMemoryHistoryBackend::OnURLsDeleted(const URLsDeletedDetails& details) {
128   DCHECK(db_);
129
130   if (details.all_history) {
131     // When all history is deleted, the individual URLs won't be listed. Just
132     // create a new database to quickly clear everything out.
133     db_.reset(new InMemoryDatabase);
134     if (!db_->InitFromScratch())
135       db_.reset();
136     return;
137   }
138
139   // Delete all matching URLs in our database.
140   for (URLRows::const_iterator row = details.rows.begin();
141        row != details.rows.end(); ++row) {
142     // This will also delete the corresponding keyword search term.
143     // Ignore errors, as we typically only cache a subset of URLRows.
144     db_->DeleteURLRow(row->id());
145   }
146 }
147
148 void InMemoryHistoryBackend::OnKeywordSearchTermUpdated(
149     const KeywordSearchUpdatedDetails& details) {
150   DCHECK(details.url_row.id());
151   db_->InsertOrUpdateURLRowByID(details.url_row);
152   db_->SetKeywordSearchTermsForURL(
153       details.url_row.id(), details.keyword_id, details.term);
154 }
155
156 void InMemoryHistoryBackend::OnKeywordSearchTermDeleted(
157     const KeywordSearchDeletedDetails& details) {
158   // For simplicity, this will not remove the corresponding URLRow, but this is
159   // okay, as the main database does not do so either.
160   db_->DeleteKeywordSearchTermForURL(details.url_row_id);
161 }
162
163 }  // namespace history