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

Side by Side Diff: chrome/browser/thumbnail_store.cc

Issue 149223: Change ThumbnailStore to use sqlite instead of individual files. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 5 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
« no previous file with comments | « chrome/browser/thumbnail_store.h ('k') | chrome/browser/thumbnail_store_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/thumbnail_store.h" 5 #include "chrome/browser/thumbnail_store.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 #include <algorithm> 8 #include <algorithm>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
11 #include "base/pickle.h"
12 #include "base/file_util.h" 11 #include "base/file_util.h"
13 #include "base/gfx/jpeg_codec.h" 12 #include "base/gfx/jpeg_codec.h"
14 #include "base/md5.h" 13 #include "base/md5.h"
15 #include "base/string_util.h" 14 #include "base/string_util.h"
16 #include "base/thread.h" 15 #include "base/thread.h"
17 #include "base/values.h" 16 #include "base/values.h"
18 #include "chrome/browser/browser_process.h" 17 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/profile.h" 18 #include "chrome/browser/profile.h"
20 #include "chrome/common/pref_service.h" 19 #include "chrome/common/pref_service.h"
21 #include "chrome/common/thumbnail_score.h" 20 #include "chrome/common/sqlite_utils.h"
22 #include "googleurl/src/gurl.h" 21 #include "googleurl/src/gurl.h"
23 #include "third_party/skia/include/core/SkBitmap.h" 22 #include "third_party/skia/include/core/SkBitmap.h"
24 23
25 24
26 ThumbnailStore::ThumbnailStore() 25 ThumbnailStore::ThumbnailStore()
27 : cache_(NULL), 26 : cache_(NULL),
28 cache_initialized_(false), 27 db_(NULL),
29 hs_(NULL), 28 hs_(NULL),
30 url_blacklist_(NULL) { 29 url_blacklist_(NULL) {
31 } 30 }
32 31
33 ThumbnailStore::~ThumbnailStore() { 32 ThumbnailStore::~ThumbnailStore() {
33 CommitCacheToDB(NULL);
34 } 34 }
35 35
36 void ThumbnailStore::Init(const FilePath& file_path, Profile* profile) { 36 void ThumbnailStore::Init(const FilePath& db_name,
37 file_path_ = file_path; 37 Profile* profile) {
38 // Load thumbnails already in the database.
39 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
40 NewRunnableMethod(this, &ThumbnailStore::InitializeFromDB,
41 db_name, MessageLoop::current()));
42
43 // Take ownership of a reference to the HistoryService.
38 hs_ = profile->GetHistoryService(Profile::EXPLICIT_ACCESS); 44 hs_ = profile->GetHistoryService(Profile::EXPLICIT_ACCESS);
45
46 // Store a pointer to a persistent table of blacklisted URLs.
39 url_blacklist_ = profile->GetPrefs()-> 47 url_blacklist_ = profile->GetPrefs()->
40 GetMutableDictionary(prefs::kNTPMostVisitedURLsBlacklist); 48 GetMutableDictionary(prefs::kNTPMostVisitedURLsBlacklist);
41 49
42 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, 50 // Get the list of most visited URLs and redirect information from the
43 NewRunnableMethod(this, &ThumbnailStore::GetAllThumbnailsFromDisk, 51 // HistoryService.
44 file_path_, MessageLoop::current()));
45
46 timer_.Start(base::TimeDelta::FromMinutes(30), this, 52 timer_.Start(base::TimeDelta::FromMinutes(30), this,
47 &ThumbnailStore::UpdateURLData); 53 &ThumbnailStore::UpdateURLData);
48 UpdateURLData(); 54 UpdateURLData();
49 } 55 }
50 56
51 bool ThumbnailStore::SetPageThumbnail(const GURL& url, 57 bool ThumbnailStore::SetPageThumbnail(const GURL& url,
52 const SkBitmap& thumbnail, 58 const SkBitmap& thumbnail,
53 const ThumbnailScore& score, 59 const ThumbnailScore& score) {
54 bool write_to_disk) { 60 if (!cache_.get())
55 if (!cache_initialized_)
56 return false; 61 return false;
57 62
58 if (!ShouldStoreThumbnailForURL(url) || 63 if (!ShouldStoreThumbnailForURL(url) ||
59 (cache_->find(url) != cache_->end() && 64 (cache_->find(url) != cache_->end() &&
60 !ShouldReplaceThumbnailWith((*cache_)[url].second, score))) 65 !ShouldReplaceThumbnailWith((*cache_)[url].score_, score)))
61 return true; 66 return true;
62 67
63 base::TimeTicks encode_start = base::TimeTicks::Now(); 68 base::TimeTicks encode_start = base::TimeTicks::Now();
64 69
65 // Encode the SkBitmap to jpeg and add to cache. 70 // Encode the SkBitmap to jpeg.
66 scoped_refptr<RefCountedBytes> jpeg_data = new RefCountedBytes; 71 scoped_refptr<RefCountedBytes> jpeg_data = new RefCountedBytes;
67 SkAutoLockPixels thumbnail_lock(thumbnail); 72 SkAutoLockPixels thumbnail_lock(thumbnail);
68 bool encoded = JPEGCodec::Encode( 73 bool encoded = JPEGCodec::Encode(
69 reinterpret_cast<unsigned char*>(thumbnail.getAddr32(0, 0)), 74 reinterpret_cast<unsigned char*>(thumbnail.getAddr32(0, 0)),
70 JPEGCodec::FORMAT_BGRA, thumbnail.width(), 75 JPEGCodec::FORMAT_BGRA, thumbnail.width(),
71 thumbnail.height(), 76 thumbnail.height(),
72 static_cast<int>(thumbnail.rowBytes()), 90, 77 static_cast<int>(thumbnail.rowBytes()), 90,
73 &jpeg_data->data); 78 &jpeg_data->data);
74 79
75 base::TimeDelta delta = base::TimeTicks::Now() - encode_start; 80 base::TimeDelta delta = base::TimeTicks::Now() - encode_start;
76 HISTOGRAM_TIMES("Thumbnail.Encode", delta); 81 HISTOGRAM_TIMES("Thumbnail.Encode", delta);
77 82
78 if (!encoded) 83 if (!encoded)
79 return false; 84 return false;
80 85
81 // Update the cache_ with the new thumbnail. 86 // Update the cache_ with the new thumbnail.
82 (*cache_)[url] = std::make_pair(jpeg_data, score); 87 (*cache_)[url] = CacheEntry(jpeg_data, score, true);
83 88
84 // Write the new thumbnail data to disk in the background on file_thread.
85 if (write_to_disk) {
86 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
87 NewRunnableMethod(this, &ThumbnailStore::WriteThumbnailToDisk, url,
88 jpeg_data, score));
89 }
90 return true; 89 return true;
91 } 90 }
92 91
93 bool ThumbnailStore::GetPageThumbnail( 92 bool ThumbnailStore::GetPageThumbnail(
94 const GURL& url, 93 const GURL& url,
95 RefCountedBytes** data) { 94 RefCountedBytes** data) {
96 if (!cache_initialized_ || IsURLBlacklisted(url)) 95 if (!cache_.get() || IsURLBlacklisted(url))
97 return false; 96 return false;
98 97
99 // Look up the |url| in the redirect list to find the final destination 98 // Look up the |url| in the redirect list to find the final destination
100 // which is the key into the |cache_|. 99 // which is the key into the |cache_|.
101 history::RedirectMap::iterator it = redirect_urls_->find(url); 100 history::RedirectMap::iterator it = redirect_urls_->find(url);
102 if (it == redirect_urls_->end()) 101 if (it != redirect_urls_->end()) {
103 return false; 102 // Return the first available thumbnail starting at the end of the
104 103 // redirect list.
105 // Return the first available thumbnail starting at the end of the 104 history::RedirectList::reverse_iterator rit;
106 // redirect list. 105 for (rit = it->second->data.rbegin();
107 history::RedirectList::reverse_iterator rit; 106 rit != it->second->data.rend(); ++rit) {
108 for (rit = it->second->data.rbegin(); 107 if (cache_->find(*rit) != cache_->end()) {
109 rit != it->second->data.rend(); ++rit) { 108 *data = (*cache_)[*rit].data_.get();
110 if (cache_->find(*rit) != cache_->end()) { 109 (*data)->AddRef();
111 *data = (*cache_)[*rit].first; 110 return true;
112 (*data)->AddRef(); 111 }
113 return true;
114 } 112 }
115 } 113 }
116 114
117 // TODO(meelapshah) bug 14643: check past redirect lists 115 // TODO(meelapshah) bug 14643: check past redirect lists
118 116
119 if (cache_->find(url) == cache_->end()) 117 if (cache_->find(url) == cache_->end())
120 return false; 118 return false;
121 119
122 *data = (*cache_)[url].first; 120 *data = (*cache_)[url].data_.get();
123 (*data)->AddRef(); 121 (*data)->AddRef();
124 return true; 122 return true;
125 } 123 }
126 124
127 void ThumbnailStore::UpdateURLData() { 125 void ThumbnailStore::UpdateURLData() {
128 int result_count = ThumbnailStore::kMaxCacheSize + url_blacklist_->GetSize(); 126 int result_count = ThumbnailStore::kMaxCacheSize + url_blacklist_->GetSize();
129 hs_->QueryTopURLsAndRedirects(result_count, &consumer_, 127 hs_->QueryTopURLsAndRedirects(result_count, &consumer_,
130 NewCallback(this, &ThumbnailStore::OnURLDataAvailable)); 128 NewCallback(this, &ThumbnailStore::OnURLDataAvailable));
131 } 129 }
132 130
133 void ThumbnailStore::OnURLDataAvailable(std::vector<GURL>* urls, 131 void ThumbnailStore::OnURLDataAvailable(std::vector<GURL>* urls,
134 history::RedirectMap* redirects) { 132 history::RedirectMap* redirects) {
135 DCHECK(urls); 133 DCHECK(urls);
136 DCHECK(redirects); 134 DCHECK(redirects);
137 135
138 most_visited_urls_.reset(new std::vector<GURL>(*urls)); 136 most_visited_urls_.reset(new std::vector<GURL>(*urls));
139 redirect_urls_.reset(new history::RedirectMap(*redirects)); 137 redirect_urls_.reset(new history::RedirectMap(*redirects));
140 CleanCacheData(); 138 CleanCacheData();
141 } 139 }
142 140
143 void ThumbnailStore::CleanCacheData() { 141 void ThumbnailStore::CleanCacheData() {
144 if (!cache_initialized_) 142 if (!cache_.get())
145 return; 143 return;
146 144
147 // For each URL in the cache, search the RedirectMap for the originating URL. 145 // For each URL in the cache, search the RedirectMap for the originating URL.
148 // If this URL is blacklisted or not in the most visited list, delete the 146 // If this URL is blacklisted or not in the most visited list, delete the
149 // thumbnail data for it from the cache and from disk in the background. 147 // thumbnail data for it from the cache and from disk in the background.
150 scoped_refptr<RefCountedVector<GURL> > old_urls = new RefCountedVector<GURL>; 148 scoped_refptr<RefCountedVector<GURL> > old_urls = new RefCountedVector<GURL>;
151 for (ThumbnailStore::Cache::iterator cache_it = cache_->begin(); 149 for (Cache::iterator cache_it = cache_->begin();
152 cache_it != cache_->end();) { 150 cache_it != cache_->end();) {
153 const GURL* url = NULL; 151 const GURL* url = NULL;
154 for (history::RedirectMap::iterator it = redirect_urls_->begin(); 152 for (history::RedirectMap::iterator it = redirect_urls_->begin();
155 it != redirect_urls_->end(); ++it) { 153 it != redirect_urls_->end(); ++it) {
156 if (cache_it->first == it->first || 154 if (cache_it->first == it->first ||
157 (it->second->data.size() && 155 (it->second->data.size() &&
158 cache_it->first == it->second->data.back())) { 156 cache_it->first == it->second->data.back())) {
159 url = &it->first; 157 url = &it->first;
160 break; 158 break;
161 } 159 }
162 } 160 }
163 161
164 if (url == NULL || IsURLBlacklisted(*url) || !IsPopular(*url)) { 162 if (url == NULL || IsURLBlacklisted(*url) || !IsPopular(*url)) {
165 old_urls->data.push_back(cache_it->first); 163 old_urls->data.push_back(cache_it->first);
166 cache_->erase(cache_it++); 164 cache_->erase(cache_it++);
167 } else { 165 } else {
168 cache_it++; 166 cache_it++;
169 } 167 }
170 } 168 }
171 169
172 if (old_urls->data.size()) { 170 if (old_urls->data.size()) {
173 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, 171 g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE,
174 NewRunnableMethod(this, &ThumbnailStore::DeleteThumbnails, old_urls)); 172 NewRunnableMethod(this, &ThumbnailStore::CommitCacheToDB, old_urls));
175 } 173 }
176 } 174 }
177 175
178 void ThumbnailStore::DeleteThumbnails( 176 void ThumbnailStore::CommitCacheToDB(
179 scoped_refptr<RefCountedVector<GURL> > thumbnail_urls) const { 177 scoped_refptr<RefCountedVector<GURL> > stale_urls) const {
180 for (std::vector<GURL>::iterator it = thumbnail_urls->data.begin(); 178 if (!db_)
181 it != thumbnail_urls->data.end(); ++it) 179 return;
182 file_util::Delete(file_path_.AppendASCII(MD5String(it->spec())), false); 180
181 // Delete old thumbnails.
182 if (stale_urls.get()) {
183 for (std::vector<GURL>::iterator it = stale_urls->data.begin();
184 it != stale_urls->data.end(); ++it) {
185 SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
186 "DELETE FROM thumbnails WHERE url=?");
187 statement->bind_string(0, it->spec());
188 if (statement->step() != SQLITE_DONE)
189 NOTREACHED();
190 }
191 }
192
193 // Update cached thumbnails.
194 for (Cache::iterator it = cache_->begin(); it != cache_->end(); ++it) {
195 if (!it->second.dirty_)
196 continue;
197
198 SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
199 "INSERT OR REPLACE INTO thumbnails "
200 "(url, boring_score, good_clipping, at_top, time_taken, data) "
201 "VALUES (?,?,?,?,?,?)");
202 statement->bind_string(0, it->first.spec());
203 statement->bind_double(1, it->second.score_.boring_score);
204 statement->bind_bool(2, it->second.score_.good_clipping);
205 statement->bind_bool(3, it->second.score_.at_top);
206 statement->bind_int64(4, it->second.score_.time_at_snapshot.
207 ToInternalValue());
208 statement->bind_blob(5, &it->second.data_->data[0],
209 static_cast<int>(it->second.data_->data.size()));
210 if (statement->step() != SQLITE_DONE)
211 DLOG(WARNING) << "Unable to insert thumbnail for URL";
212 else
213 it->second.dirty_ = false;
214 }
183 } 215 }
184 216
185 void ThumbnailStore::GetAllThumbnailsFromDisk(FilePath filepath, 217 void ThumbnailStore::InitializeFromDB(const FilePath& db_name,
186 MessageLoop* cb_loop) { 218 MessageLoop* cb_loop) {
219 if (OpenSqliteDb(db_name, &db_) != SQLITE_OK)
220 return;
221
222 // Use a large page size since the thumbnails we are storing are typically
223 // large, a small cache size since we cache in memory and don't go to disk
224 // often, and take exclusive access since nobody else uses this db.
225 sqlite3_exec(db_, "PRAGMA page_size=4096 "
226 "PRAGMA cache_size=64 "
227 "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, NULL);
228
229 statement_cache_ = new SqliteStatementCache;
230
231 // Use local DBCloseScoper so that if we cannot create the table and
232 // need to return, the |db_| and |statement_cache_| are closed properly.
233 history::DBCloseScoper scoper(&db_, &statement_cache_);
234
235 if (!DoesSqliteTableExist(db_, "thumbnails")) {
236 if (sqlite3_exec(db_, "CREATE TABLE thumbnails ("
237 "url LONGVARCHAR PRIMARY KEY,"
238 "boring_score DOUBLE DEFAULT 1.0,"
239 "good_clipping INTEGER DEFAULT 0,"
240 "at_top INTEGER DEFAULT 0,"
241 "time_taken INTEGER DEFAULT 0,"
242 "data BLOB)", NULL, NULL, NULL) != SQLITE_OK)
243 return;
244 }
245
246 statement_cache_->set_db(db_);
247
248 // Now we can use a DBCloseScoper at the object scope.
249 scoper.Detach();
250 close_scoper_.Attach(&db_, &statement_cache_);
251
252 if (cb_loop)
253 GetAllThumbnailsFromDisk(cb_loop);
254 }
255
256 void ThumbnailStore::GetAllThumbnailsFromDisk(MessageLoop* cb_loop) {
187 ThumbnailStore::Cache* cache = new ThumbnailStore::Cache; 257 ThumbnailStore::Cache* cache = new ThumbnailStore::Cache;
188 258
189 // Create the specified directory if it does not exist. 259 SQLITE_UNIQUE_STATEMENT(statement, *statement_cache_,
190 if (!file_util::DirectoryExists(filepath)) { 260 "SELECT * FROM thumbnails");
191 file_util::CreateDirectory(filepath);
192 } else {
193 // Walk the directory and read the thumbnail data from disk.
194 FilePath path;
195 GURL url;
196 RefCountedBytes* data;
197 ThumbnailScore score;
198 file_util::FileEnumerator fenum(filepath, false,
199 file_util::FileEnumerator::FILES);
200 261
201 while (!(path = fenum.Next()).empty()) { 262 while (statement->step() == SQLITE_ROW) {
202 data = new RefCountedBytes; 263 GURL url(statement->column_string(0));
203 if (GetPageThumbnailFromDisk(path, &url, data, &score)) 264 ThumbnailScore score(statement->column_double(1), // Boring score
204 (*cache)[url] = std::make_pair(data, score); 265 statement->column_bool(2), // Good clipping
205 else 266 statement->column_bool(3), // At top
206 delete data; 267 base::Time::FromInternalValue(
207 } 268 statement->column_int64(4))); // Time taken
269 scoped_refptr<RefCountedBytes> data = new RefCountedBytes;
270 if (statement->column_blob_as_vector(5, &data->data))
271 (*cache)[url] = CacheEntry(data, score, false);
208 } 272 }
273
209 cb_loop->PostTask(FROM_HERE, 274 cb_loop->PostTask(FROM_HERE,
210 NewRunnableMethod(this, &ThumbnailStore::OnDiskDataAvailable, cache)); 275 NewRunnableMethod(this, &ThumbnailStore::OnDiskDataAvailable, cache));
211 } 276 }
212 277
213 bool ThumbnailStore::GetPageThumbnailFromDisk(const FilePath& file,
214 GURL* url,
215 RefCountedBytes* data,
216 ThumbnailScore* score) const {
217 int64 file_size;
218 if (!file_util::GetFileSize(file, &file_size))
219 return false;
220
221 // Read the file into a buffer.
222 std::vector<char> file_data;
223 file_data.resize(static_cast<unsigned int>(file_size));
224 if (file_util::ReadFile(file, &file_data[0],
225 static_cast<int>(file_size)) == -1)
226 return false;
227
228 // Unpack the url, ThumbnailScore and JPEG size from the buffer.
229 std::string url_string;
230 unsigned int jpeg_len;
231 void* iter = NULL;
232 Pickle packed(&file_data[0], static_cast<int>(file_size));
233
234 if (!packed.ReadString(&iter, &url_string) ||
235 !UnpackScore(score, packed, iter) ||
236 !packed.ReadUInt32(&iter, &jpeg_len))
237 return false;
238
239 // Store the url to the out parameter.
240 GURL temp_url(url_string);
241 url->Swap(&temp_url);
242
243 // Unpack the JPEG data from the buffer.
244 const char* jpeg_data = NULL;
245 int out_len;
246
247 if (!packed.ReadData(&iter, &jpeg_data, &out_len) ||
248 out_len != static_cast<int>(jpeg_len))
249 return false;
250
251 // Copy jpeg data to the out parameter.
252 data->data.resize(jpeg_len);
253 memcpy(&data->data[0], jpeg_data, jpeg_len);
254
255 return true;
256 }
257
258 void ThumbnailStore::OnDiskDataAvailable(ThumbnailStore::Cache* cache) { 278 void ThumbnailStore::OnDiskDataAvailable(ThumbnailStore::Cache* cache) {
259 if (cache) { 279 if (cache)
260 cache_.reset(cache); 280 cache_.reset(cache);
261 cache_initialized_ = true;
262 }
263 }
264
265 bool ThumbnailStore::WriteThumbnailToDisk(const GURL& url,
266 scoped_refptr<RefCountedBytes> data,
267 const ThumbnailScore& score) const {
268 Pickle packed;
269 FilePath file = file_path_.AppendASCII(MD5String(url.spec()));
270
271 // Pack the url, ThumbnailScore, and the JPEG data.
272 packed.WriteString(url.spec());
273 PackScore(score, &packed);
274 packed.WriteUInt32(data->data.size());
275 packed.WriteData(reinterpret_cast<char*>(&data->data[0]), data->data.size());
276
277 // Write the packed data to a file.
278 file_util::Delete(file, false);
279 return file_util::WriteFile(file,
280 reinterpret_cast<const char*>(packed.data()),
281 packed.size()) != -1;
282 }
283
284 void ThumbnailStore::PackScore(const ThumbnailScore& score,
285 Pickle* packed) const {
286 // Pack the contents of the given ThumbnailScore into the given Pickle.
287 packed->WriteData(reinterpret_cast<const char*>(&score.boring_score),
288 sizeof(score.boring_score));
289 packed->WriteBool(score.at_top);
290 packed->WriteBool(score.good_clipping);
291 packed->WriteInt64(score.time_at_snapshot.ToInternalValue());
292 }
293
294 bool ThumbnailStore::UnpackScore(ThumbnailScore* score, const Pickle& packed,
295 void*& iter) const {
296 // Unpack a ThumbnailScore from the given Pickle and iterator.
297 const char* boring = NULL;
298 int out_len;
299 int64 us;
300
301 if (!packed.ReadData(&iter, &boring, &out_len) ||
302 !packed.ReadBool(&iter, &score->at_top) ||
303 !packed.ReadBool(&iter, &score->good_clipping) ||
304 !packed.ReadInt64(&iter, &us))
305 return false;
306
307 if (out_len != sizeof(score->boring_score))
308 return false;
309
310 memcpy(&score->boring_score, boring, sizeof(score->boring_score));
311 score->time_at_snapshot = base::Time::FromInternalValue(us);
312 return true;
313 } 281 }
314 282
315 bool ThumbnailStore::ShouldStoreThumbnailForURL(const GURL& url) const { 283 bool ThumbnailStore::ShouldStoreThumbnailForURL(const GURL& url) const {
316 if (IsURLBlacklisted(url) || cache_->size() >= ThumbnailStore::kMaxCacheSize) 284 if (IsURLBlacklisted(url) || cache_->size() >= ThumbnailStore::kMaxCacheSize)
317 return false; 285 return false;
318 286
319 return most_visited_urls_->size() < ThumbnailStore::kMaxCacheSize || 287 return most_visited_urls_->size() < ThumbnailStore::kMaxCacheSize ||
320 IsPopular(url); 288 IsPopular(url);
321 } 289 }
322 290
323 bool ThumbnailStore::IsURLBlacklisted(const GURL& url) const { 291 bool ThumbnailStore::IsURLBlacklisted(const GURL& url) const {
324 if (url_blacklist_) 292 if (url_blacklist_)
325 return url_blacklist_->HasKey(GetDictionaryKeyForURL(url.spec())); 293 return url_blacklist_->HasKey(GetDictionaryKeyForURL(url.spec()));
326 return false; 294 return false;
327 } 295 }
328 296
329 std::wstring ThumbnailStore::GetDictionaryKeyForURL( 297 std::wstring ThumbnailStore::GetDictionaryKeyForURL(
330 const std::string& url) const { 298 const std::string& url) const {
331 return ASCIIToWide(MD5String(url)); 299 return ASCIIToWide(MD5String(url));
332 } 300 }
333 301
334 bool ThumbnailStore::IsPopular(const GURL& url) const { 302 bool ThumbnailStore::IsPopular(const GURL& url) const {
335 return most_visited_urls_->end() != find(most_visited_urls_->begin(), 303 return most_visited_urls_->end() != find(most_visited_urls_->begin(),
336 most_visited_urls_->end(), 304 most_visited_urls_->end(),
337 url); 305 url);
338 } 306 }
OLDNEW
« no previous file with comments | « chrome/browser/thumbnail_store.h ('k') | chrome/browser/thumbnail_store_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698