Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(918)

Side by Side Diff: chrome/browser/history/shortcuts_backend.cc

Issue 9689085: Clean up ShortcutsProvider and related classes. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/history/shortcuts_backend.h" 5 #include "chrome/browser/history/shortcuts_backend.h"
6 6
7 #include <map> 7 #include <map>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/i18n/case_conversion.h" 13 #include "base/i18n/case_conversion.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 #include "chrome/browser/autocomplete/autocomplete.h" 15 #include "chrome/browser/autocomplete/autocomplete.h"
16 #include "chrome/browser/autocomplete/autocomplete_match.h" 16 #include "chrome/browser/autocomplete/autocomplete_match.h"
17 #include "chrome/browser/history/history.h" 17 #include "chrome/browser/history/history.h"
18 #include "chrome/browser/history/history_notifications.h" 18 #include "chrome/browser/history/history_notifications.h"
19 #include "chrome/browser/history/shortcuts_database.h" 19 #include "chrome/browser/history/shortcuts_database.h"
20 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/common/chrome_notification_types.h" 21 #include "chrome/common/chrome_notification_types.h"
22 #include "chrome/common/guid.h" 22 #include "chrome/common/guid.h"
23 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_details.h" 24 #include "content/public/browser/notification_details.h"
25 #include "content/public/browser/notification_source.h" 25 #include "content/public/browser/notification_source.h"
26 26
27 using content::BrowserThread; 27 using content::BrowserThread;
28 28
29 namespace {
30
31 // Takes Match classification vector and removes all matched positions,
32 // compacting repetitions if necessary.
33 void StripMatchMarkersFromClassifications(ACMatchClassifications* matches) {
34 DCHECK(matches);
35 ACMatchClassifications unmatched;
36 for (ACMatchClassifications::iterator i = matches->begin();
37 i != matches->end(); ++i) {
38 AutocompleteMatch::AddLastClassificationIfNecessary(&unmatched, i->offset,
39 i->style & ~ACMatchClassification::MATCH);
40 }
41 matches->swap(unmatched);
42 }
43
44 } // namespace
45
29 namespace history { 46 namespace history {
30 47
48 // ShortcutsBackend::Shortcut -------------------------------------------------
49
50 ShortcutsBackend::Shortcut::Shortcut(
51 const std::string& id,
52 const string16& text,
53 const GURL& url,
54 const string16& contents,
55 const ACMatchClassifications& contents_class,
56 const string16& description,
57 const ACMatchClassifications& description_class,
58 const base::Time& last_access_time,
59 int number_of_hits)
60 : id(id),
61 text(text),
62 url(url),
63 contents(contents),
64 contents_class(contents_class),
65 description(description),
66 description_class(description_class),
67 last_access_time(last_access_time),
68 number_of_hits(number_of_hits) {
69 StripMatchMarkersFromClassifications(&this->contents_class);
70 StripMatchMarkersFromClassifications(&this->description_class);
71 }
72
73 ShortcutsBackend::Shortcut::Shortcut()
74 : last_access_time(base::Time::Now()),
75 number_of_hits(0) {
76 }
77
78 ShortcutsBackend::Shortcut::~Shortcut() {
79 }
80
81
82 // ShortcutsBackend -----------------------------------------------------------
83
31 ShortcutsBackend::ShortcutsBackend(const FilePath& db_folder_path, 84 ShortcutsBackend::ShortcutsBackend(const FilePath& db_folder_path,
32 Profile *profile) 85 Profile *profile)
33 : current_state_(NOT_INITIALIZED), 86 : current_state_(NOT_INITIALIZED),
34 db_(new ShortcutsDatabase(db_folder_path)), 87 db_(new ShortcutsDatabase(db_folder_path)),
35 no_db_access_(db_folder_path.empty()) { 88 no_db_access_(db_folder_path.empty()) {
36 // |profile| can be NULL in tests. 89 // |profile| can be NULL in tests.
37 if (profile) { 90 if (profile) {
38 notification_registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL, 91 notification_registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
39 content::Source<Profile>(profile)); 92 content::Source<Profile>(profile));
40 notification_registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, 93 notification_registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED,
41 content::Source<Profile>(profile)); 94 content::Source<Profile>(profile));
42 } 95 }
43 } 96 }
44 97
45 ShortcutsBackend::~ShortcutsBackend() {} 98 ShortcutsBackend::~ShortcutsBackend() {}
46 99
47 bool ShortcutsBackend::Init() { 100 bool ShortcutsBackend::Init() {
48 if (current_state_ == NOT_INITIALIZED) { 101 if (current_state_ != NOT_INITIALIZED)
49 current_state_ = INITIALIZING;
50 if (no_db_access_) {
51 current_state_ = INITIALIZED;
52 return true;
53 } else {
54 return BrowserThread::PostTask(
55 BrowserThread::DB, FROM_HERE,
56 base::Bind(&ShortcutsBackend::InitInternal, this));
57 }
58 } else {
59 return false; 102 return false;
103
104 if (no_db_access_) {
105 current_state_ = INITIALIZED;
106 return true;
60 } 107 }
108
109 current_state_ = INITIALIZING;
110 return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
111 base::Bind(&ShortcutsBackend::InitInternal, this));
61 } 112 }
62 113
63 bool ShortcutsBackend::AddShortcut( 114 bool ShortcutsBackend::AddShortcut(const Shortcut& shortcut) {
64 const shortcuts_provider::Shortcut& shortcut) {
65 if (!initialized()) 115 if (!initialized())
66 return false; 116 return false;
67 DCHECK(guid_map_.find(shortcut.id) == guid_map_.end()); 117 DCHECK(guid_map_.find(shortcut.id) == guid_map_.end());
68 guid_map_[shortcut.id] = shortcuts_map_.insert( 118 guid_map_[shortcut.id] = shortcuts_map_.insert(
69 std::make_pair(base::i18n::ToLower(shortcut.text), shortcut)); 119 std::make_pair(base::i18n::ToLower(shortcut.text), shortcut));
70 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 120 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
71 OnShortcutsChanged()); 121 OnShortcutsChanged());
72 if (no_db_access_) 122 return no_db_access_ || BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
73 return true;
74 return BrowserThread::PostTask(
75 BrowserThread::DB, FROM_HERE,
76 base::Bind(base::IgnoreResult(&ShortcutsDatabase::AddShortcut), 123 base::Bind(base::IgnoreResult(&ShortcutsDatabase::AddShortcut),
77 db_.get(), shortcut)); 124 db_.get(), shortcut));
78 } 125 }
79 126
80 bool ShortcutsBackend::UpdateShortcut( 127 bool ShortcutsBackend::UpdateShortcut(const Shortcut& shortcut) {
81 const shortcuts_provider::Shortcut& shortcut) {
82 if (!initialized()) 128 if (!initialized())
83 return false; 129 return false;
84 shortcuts_provider::GuidToShortcutsIteratorMap::iterator it = 130 GuidToShortcutsIteratorMap::iterator it = guid_map_.find(shortcut.id);
85 guid_map_.find(shortcut.id);
86 if (it != guid_map_.end()) 131 if (it != guid_map_.end())
87 shortcuts_map_.erase(it->second); 132 shortcuts_map_.erase(it->second);
88 guid_map_[shortcut.id] = shortcuts_map_.insert( 133 guid_map_[shortcut.id] = shortcuts_map_.insert(
89 std::make_pair(base::i18n::ToLower(shortcut.text), shortcut)); 134 std::make_pair(base::i18n::ToLower(shortcut.text), shortcut));
90 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 135 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
91 OnShortcutsChanged()); 136 OnShortcutsChanged());
92 if (no_db_access_) 137 return no_db_access_ || BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
93 return true; 138 base::Bind(base::IgnoreResult(&ShortcutsDatabase::UpdateShortcut),
94 return BrowserThread::PostTask( 139 db_.get(), shortcut));
95 BrowserThread::DB, FROM_HERE,
96 base::Bind(base::IgnoreResult(&ShortcutsDatabase::UpdateShortcut),
97 db_.get(), shortcut));
98 } 140 }
99 141
100 bool ShortcutsBackend::DeleteShortcutsWithIds( 142 bool ShortcutsBackend::DeleteShortcutsWithIds(
101 const std::vector<std::string>& shortcut_ids) { 143 const std::vector<std::string>& shortcut_ids) {
102 if (!initialized()) 144 if (!initialized())
103 return false; 145 return false;
104 for (size_t i = 0; i < shortcut_ids.size(); ++i) { 146 for (size_t i = 0; i < shortcut_ids.size(); ++i) {
105 shortcuts_provider::GuidToShortcutsIteratorMap::iterator it = 147 GuidToShortcutsIteratorMap::iterator it = guid_map_.find(shortcut_ids[i]);
106 guid_map_.find(shortcut_ids[i]);
107 if (it != guid_map_.end()) { 148 if (it != guid_map_.end()) {
108 shortcuts_map_.erase(it->second); 149 shortcuts_map_.erase(it->second);
109 guid_map_.erase(it); 150 guid_map_.erase(it);
110 } 151 }
111 } 152 }
112 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 153 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
113 OnShortcutsChanged()); 154 OnShortcutsChanged());
114 if (no_db_access_) 155 return no_db_access_ || BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
115 return true; 156 base::Bind(base::IgnoreResult(&ShortcutsDatabase::DeleteShortcutsWithIds),
116 return BrowserThread::PostTask( 157 db_.get(), shortcut_ids));
117 BrowserThread::DB, FROM_HERE,
118 base::Bind(
119 base::IgnoreResult(&ShortcutsDatabase::DeleteShortcutsWithIds),
120 db_.get(), shortcut_ids));
121 } 158 }
122 159
123 bool ShortcutsBackend::DeleteShortcutsWithUrl(const GURL& shortcut_url) { 160 bool ShortcutsBackend::DeleteShortcutsWithUrl(const GURL& shortcut_url) {
124 if (!initialized()) 161 if (!initialized())
125 return false; 162 return false;
126 std::vector<std::string> shortcut_ids; 163 std::vector<std::string> shortcut_ids;
127 for (shortcuts_provider::GuidToShortcutsIteratorMap::iterator 164 for (GuidToShortcutsIteratorMap::iterator it = guid_map_.begin();
128 it = guid_map_.begin();
129 it != guid_map_.end();) { 165 it != guid_map_.end();) {
130 if (it->second->second.url == shortcut_url) { 166 if (it->second->second.url == shortcut_url) {
131 shortcut_ids.push_back(it->first); 167 shortcut_ids.push_back(it->first);
132 shortcuts_map_.erase(it->second); 168 shortcuts_map_.erase(it->second);
133 guid_map_.erase(it++); 169 guid_map_.erase(it++);
134 } else { 170 } else {
135 ++it; 171 ++it;
136 } 172 }
137 } 173 }
138 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 174 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
139 OnShortcutsChanged()); 175 OnShortcutsChanged());
140 if (no_db_access_) 176 return no_db_access_ || BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
141 return true; 177 base::Bind(base::IgnoreResult(&ShortcutsDatabase::DeleteShortcutsWithUrl),
142 return BrowserThread::PostTask( 178 db_.get(), shortcut_url.spec()));
143 BrowserThread::DB, FROM_HERE,
144 base::Bind(
145 base::IgnoreResult(&ShortcutsDatabase::DeleteShortcutsWithUrl),
146 db_.get(), shortcut_url.spec()));
147 } 179 }
148 180
149 bool ShortcutsBackend::DeleteAllShortcuts() { 181 bool ShortcutsBackend::DeleteAllShortcuts() {
150 if (!initialized()) 182 if (!initialized())
151 return false; 183 return false;
152 shortcuts_map_.clear(); 184 shortcuts_map_.clear();
153 guid_map_.clear(); 185 guid_map_.clear();
154 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 186 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
155 OnShortcutsChanged()); 187 OnShortcutsChanged());
156 if (no_db_access_) 188 return no_db_access_ || BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
157 return true; 189 base::Bind(base::IgnoreResult(&ShortcutsDatabase::DeleteAllShortcuts),
158 return BrowserThread::PostTask( 190 db_.get()));
159 BrowserThread::DB, FROM_HERE,
160 base::Bind(
161 base::IgnoreResult(&ShortcutsDatabase::DeleteAllShortcuts),
162 db_.get()));
163 } 191 }
164 192
165 void ShortcutsBackend::InitInternal() { 193 void ShortcutsBackend::InitInternal() {
166 DCHECK(current_state_ == INITIALIZING); 194 DCHECK(current_state_ == INITIALIZING);
167 db_->Init(); 195 db_->Init();
168 shortcuts_provider::GuidToShortcutMap shortcuts; 196 ShortcutsDatabase::GuidToShortcutMap shortcuts;
169 db_->LoadShortcuts(&shortcuts); 197 db_->LoadShortcuts(&shortcuts);
170 temp_shortcuts_map_.reset(new shortcuts_provider::ShortcutMap); 198 temp_shortcuts_map_.reset(new ShortcutMap);
171 temp_guid_map_.reset(new shortcuts_provider::GuidToShortcutsIteratorMap); 199 temp_guid_map_.reset(new GuidToShortcutsIteratorMap);
172 for (shortcuts_provider::GuidToShortcutMap::iterator it = shortcuts.begin(); 200 for (ShortcutsDatabase::GuidToShortcutMap::iterator it = shortcuts.begin();
173 it != shortcuts.end(); ++it) { 201 it != shortcuts.end(); ++it) {
174 (*temp_guid_map_)[it->first] = temp_shortcuts_map_->insert( 202 (*temp_guid_map_)[it->first] = temp_shortcuts_map_->insert(
175 std::make_pair(base::i18n::ToLower(it->second.text), it->second)); 203 std::make_pair(base::i18n::ToLower(it->second.text), it->second));
176 } 204 }
177 BrowserThread::PostTask( 205 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
178 BrowserThread::UI, FROM_HERE,
179 base::Bind(&ShortcutsBackend::InitCompleted, this)); 206 base::Bind(&ShortcutsBackend::InitCompleted, this));
180 } 207 }
181 208
182 void ShortcutsBackend::InitCompleted() { 209 void ShortcutsBackend::InitCompleted() {
183 temp_guid_map_->swap(guid_map_); 210 temp_guid_map_->swap(guid_map_);
184 temp_shortcuts_map_->swap(shortcuts_map_); 211 temp_shortcuts_map_->swap(shortcuts_map_);
185 temp_shortcuts_map_.reset(NULL); 212 temp_shortcuts_map_.reset(NULL);
186 temp_guid_map_.reset(NULL); 213 temp_guid_map_.reset(NULL);
187 current_state_ = INITIALIZED; 214 current_state_ = INITIALIZED;
188 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_, 215 FOR_EACH_OBSERVER(ShortcutsBackendObserver, observer_list_,
189 OnShortcutsLoaded()); 216 OnShortcutsLoaded());
190 } 217 }
191 218
192 // content::NotificationObserver: 219 // content::NotificationObserver:
193 void ShortcutsBackend::Observe(int type, 220 void ShortcutsBackend::Observe(int type,
194 const content::NotificationSource& source, 221 const content::NotificationSource& source,
195 const content::NotificationDetails& details) { 222 const content::NotificationDetails& details) {
196 if (current_state_ != INITIALIZED) 223 if (current_state_ != INITIALIZED)
197 return; 224 return;
198 if (type == chrome::NOTIFICATION_HISTORY_URLS_DELETED) { 225 if (type == chrome::NOTIFICATION_HISTORY_URLS_DELETED) {
199 if (content::Details<const history::URLsDeletedDetails>(details)-> 226 if (content::Details<const history::URLsDeletedDetails>(details)->
200 all_history) { 227 all_history) {
201 DeleteAllShortcuts(); 228 DeleteAllShortcuts();
202 } 229 }
203 const std::set<GURL>& urls = 230 const std::set<GURL>& urls =
204 content::Details<const history::URLsDeletedDetails>(details)->urls; 231 content::Details<const history::URLsDeletedDetails>(details)->urls;
205 std::vector<std::string> shortcut_ids; 232 std::vector<std::string> shortcut_ids;
206 233
207 for (shortcuts_provider::GuidToShortcutsIteratorMap::iterator 234 for (GuidToShortcutsIteratorMap::iterator it = guid_map_.begin();
208 it = guid_map_.begin();
209 it != guid_map_.end(); ++it) { 235 it != guid_map_.end(); ++it) {
210 if (urls.find(it->second->second.url) != urls.end()) 236 if (urls.find(it->second->second.url) != urls.end())
211 shortcut_ids.push_back(it->first); 237 shortcut_ids.push_back(it->first);
212 } 238 }
213 DeleteShortcutsWithIds(shortcut_ids); 239 DeleteShortcutsWithIds(shortcut_ids);
214 return; 240 return;
215 } 241 }
216 242
217 DCHECK(type == chrome::NOTIFICATION_OMNIBOX_OPENED_URL); 243 DCHECK(type == chrome::NOTIFICATION_OMNIBOX_OPENED_URL);
218 244
219 AutocompleteLog* log = content::Details<AutocompleteLog>(details).ptr(); 245 AutocompleteLog* log = content::Details<AutocompleteLog>(details).ptr();
220 string16 text_lowercase(base::i18n::ToLower(log->text)); 246 string16 text_lowercase(base::i18n::ToLower(log->text));
221 247
222 int number_of_hits = 1;
223 std::string id;
224 const AutocompleteMatch& match(log->result.match_at(log->selected_index)); 248 const AutocompleteMatch& match(log->result.match_at(log->selected_index));
225 for (shortcuts_provider::ShortcutMap::iterator it = 249 for (ShortcutMap::iterator it = shortcuts_map_.lower_bound(text_lowercase);
226 shortcuts_map_.lower_bound(text_lowercase);
227 it != shortcuts_map_.end() && 250 it != shortcuts_map_.end() &&
228 StartsWith(it->first, text_lowercase, true); ++it) { 251 StartsWith(it->first, text_lowercase, true); ++it) {
229 if (match.destination_url == it->second.url) { 252 if (match.destination_url == it->second.url) {
230 number_of_hits = it->second.number_of_hits + 1; 253 UpdateShortcut(Shortcut(it->second.id, log->text, match.destination_url,
231 id = it->second.id; 254 match.contents, match.contents_class, match.description,
232 break; 255 match.description_class, base::Time::Now(),
256 it->second.number_of_hits + 1));
257 return;
233 } 258 }
234 } 259 }
235 shortcuts_provider::Shortcut shortcut(log->text, match.destination_url, 260 AddShortcut(Shortcut(guid::GenerateGUID(), log->text, match.destination_url,
236 match.contents, match.contents_class, match.description, 261 match.contents, match.contents_class, match.description,
237 match.description_class); 262 match.description_class, base::Time::Now(), 1));
238 shortcut.number_of_hits = number_of_hits;
239 if (number_of_hits == 1)
240 shortcut.id = guid::GenerateGUID();
241 else
242 shortcut.id = id;
243
244 if (number_of_hits == 1)
245 AddShortcut(shortcut);
246 else
247 UpdateShortcut(shortcut);
248 } 263 }
249 264
250 } // namespace history 265 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698