• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // The history system runs on a background thread so that potentially slow
6 // database operations don't delay the browser. This backend processing is
7 // represented by HistoryBackend. The HistoryService's job is to dispatch to
8 // that thread.
9 //
10 // Main thread                       History thread
11 // -----------                       --------------
12 // HistoryService <----------------> HistoryBackend
13 //                                   -> HistoryDatabase
14 //                                      -> SQLite connection to History
15 //                                   -> ThumbnailDatabase
16 //                                      -> SQLite connection to Thumbnails
17 //                                         (and favicons)
18 
19 #include "chrome/browser/history/history_service.h"
20 
21 #include "base/bind_helpers.h"
22 #include "base/callback.h"
23 #include "base/command_line.h"
24 #include "base/compiler_specific.h"
25 #include "base/location.h"
26 #include "base/memory/ref_counted.h"
27 #include "base/message_loop/message_loop.h"
28 #include "base/path_service.h"
29 #include "base/prefs/pref_service.h"
30 #include "base/thread_task_runner_handle.h"
31 #include "base/threading/thread.h"
32 #include "base/time/time.h"
33 #include "chrome/browser/autocomplete/history_url_provider.h"
34 #include "chrome/browser/browser_process.h"
35 #include "chrome/browser/chrome_notification_types.h"
36 #include "chrome/browser/history/download_row.h"
37 #include "chrome/browser/history/history_backend.h"
38 #include "chrome/browser/history/history_notifications.h"
39 #include "chrome/browser/history/history_types.h"
40 #include "chrome/browser/history/in_memory_database.h"
41 #include "chrome/browser/history/in_memory_history_backend.h"
42 #include "chrome/browser/history/in_memory_url_index.h"
43 #include "chrome/browser/history/top_sites.h"
44 #include "chrome/browser/history/visit_database.h"
45 #include "chrome/browser/history/visit_filter.h"
46 #include "chrome/browser/history/web_history_service.h"
47 #include "chrome/browser/history/web_history_service_factory.h"
48 #include "chrome/browser/profiles/profile.h"
49 #include "chrome/common/chrome_constants.h"
50 #include "chrome/common/chrome_switches.h"
51 #include "chrome/common/importer/imported_favicon_usage.h"
52 #include "chrome/common/pref_names.h"
53 #include "chrome/common/url_constants.h"
54 #include "components/history/core/browser/history_client.h"
55 #include "components/history/core/common/thumbnail_score.h"
56 #include "components/visitedlink/browser/visitedlink_master.h"
57 #include "content/public/browser/browser_thread.h"
58 #include "content/public/browser/download_item.h"
59 #include "content/public/browser/notification_service.h"
60 #include "grit/chromium_strings.h"
61 #include "grit/generated_resources.h"
62 #include "sync/api/sync_error_factory.h"
63 #include "third_party/skia/include/core/SkBitmap.h"
64 
65 using base::Time;
66 using history::HistoryBackend;
67 
68 namespace {
69 
70 static const char* kHistoryThreadName = "Chrome_HistoryThread";
71 
RunWithFaviconResults(const favicon_base::FaviconResultsCallback & callback,std::vector<favicon_base::FaviconRawBitmapResult> * bitmap_results)72 void RunWithFaviconResults(
73     const favicon_base::FaviconResultsCallback& callback,
74     std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) {
75   callback.Run(*bitmap_results);
76 }
77 
RunWithFaviconResult(const favicon_base::FaviconRawBitmapCallback & callback,favicon_base::FaviconRawBitmapResult * bitmap_result)78 void RunWithFaviconResult(
79     const favicon_base::FaviconRawBitmapCallback& callback,
80     favicon_base::FaviconRawBitmapResult* bitmap_result) {
81   callback.Run(*bitmap_result);
82 }
83 
RunWithQueryURLResult(const HistoryService::QueryURLCallback & callback,const HistoryBackend::QueryURLResult * result)84 void RunWithQueryURLResult(const HistoryService::QueryURLCallback& callback,
85                            const HistoryBackend::QueryURLResult* result) {
86   callback.Run(result->success, result->row, result->visits);
87 }
88 
89 // Extract history::URLRows into GURLs for VisitedLinkMaster.
90 class URLIteratorFromURLRows
91     : public visitedlink::VisitedLinkMaster::URLIterator {
92  public:
URLIteratorFromURLRows(const history::URLRows & url_rows)93   explicit URLIteratorFromURLRows(const history::URLRows& url_rows)
94       : itr_(url_rows.begin()),
95         end_(url_rows.end()) {
96   }
97 
NextURL()98   virtual const GURL& NextURL() OVERRIDE {
99     return (itr_++)->url();
100   }
101 
HasNextURL() const102   virtual bool HasNextURL() const OVERRIDE {
103     return itr_ != end_;
104   }
105 
106  private:
107   history::URLRows::const_iterator itr_;
108   history::URLRows::const_iterator end_;
109 
110   DISALLOW_COPY_AND_ASSIGN(URLIteratorFromURLRows);
111 };
112 
113 // Callback from WebHistoryService::ExpireWebHistory().
ExpireWebHistoryComplete(bool success)114 void ExpireWebHistoryComplete(bool success) {
115   // Ignore the result.
116   //
117   // TODO(davidben): ExpireLocalAndRemoteHistoryBetween callback should not fire
118   // until this completes.
119 }
120 
121 }  // namespace
122 
123 // Sends messages from the backend to us on the main thread. This must be a
124 // separate class from the history service so that it can hold a reference to
125 // the history service (otherwise we would have to manually AddRef and
126 // Release when the Backend has a reference to us).
127 class HistoryService::BackendDelegate : public HistoryBackend::Delegate {
128  public:
BackendDelegate(const base::WeakPtr<HistoryService> & history_service,const scoped_refptr<base::SequencedTaskRunner> & service_task_runner,Profile * profile)129   BackendDelegate(
130       const base::WeakPtr<HistoryService>& history_service,
131       const scoped_refptr<base::SequencedTaskRunner>& service_task_runner,
132       Profile* profile)
133       : history_service_(history_service),
134         service_task_runner_(service_task_runner),
135         profile_(profile) {
136   }
137 
NotifyProfileError(sql::InitStatus init_status)138   virtual void NotifyProfileError(sql::InitStatus init_status) OVERRIDE {
139     // Send to the history service on the main thread.
140     service_task_runner_->PostTask(
141         FROM_HERE,
142         base::Bind(&HistoryService::NotifyProfileError, history_service_,
143                    init_status));
144   }
145 
SetInMemoryBackend(scoped_ptr<history::InMemoryHistoryBackend> backend)146   virtual void SetInMemoryBackend(
147       scoped_ptr<history::InMemoryHistoryBackend> backend) OVERRIDE {
148     // Send the backend to the history service on the main thread.
149     service_task_runner_->PostTask(
150         FROM_HERE,
151         base::Bind(&HistoryService::SetInMemoryBackend, history_service_,
152                    base::Passed(&backend)));
153   }
154 
BroadcastNotifications(int type,scoped_ptr<history::HistoryDetails> details)155   virtual void BroadcastNotifications(
156       int type,
157       scoped_ptr<history::HistoryDetails> details) OVERRIDE {
158     // Send the notification on the history thread.
159     if (content::NotificationService::current()) {
160       content::Details<history::HistoryDetails> det(details.get());
161       content::NotificationService::current()->Notify(
162           type, content::Source<Profile>(profile_), det);
163     }
164     // Send the notification to the history service on the main thread.
165     service_task_runner_->PostTask(
166         FROM_HERE,
167         base::Bind(&HistoryService::BroadcastNotificationsHelper,
168                    history_service_, type, base::Passed(&details)));
169   }
170 
DBLoaded()171   virtual void DBLoaded() OVERRIDE {
172     service_task_runner_->PostTask(
173         FROM_HERE,
174         base::Bind(&HistoryService::OnDBLoaded, history_service_));
175   }
176 
NotifyVisitDBObserversOnAddVisit(const history::BriefVisitInfo & info)177   virtual void NotifyVisitDBObserversOnAddVisit(
178       const history::BriefVisitInfo& info) OVERRIDE {
179     service_task_runner_->PostTask(
180         FROM_HERE,
181         base::Bind(&HistoryService::NotifyVisitDBObserversOnAddVisit,
182                    history_service_, info));
183   }
184 
185  private:
186   const base::WeakPtr<HistoryService> history_service_;
187   const scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
188   Profile* const profile_;
189 };
190 
191 // The history thread is intentionally not a BrowserThread because the
192 // sync integration unit tests depend on being able to create more than one
193 // history thread.
HistoryService()194 HistoryService::HistoryService()
195     : weak_ptr_factory_(this),
196       thread_(new base::Thread(kHistoryThreadName)),
197       history_client_(NULL),
198       profile_(NULL),
199       backend_loaded_(false),
200       no_db_(false) {
201 }
202 
HistoryService(history::HistoryClient * client,Profile * profile)203 HistoryService::HistoryService(history::HistoryClient* client, Profile* profile)
204     : weak_ptr_factory_(this),
205       thread_(new base::Thread(kHistoryThreadName)),
206       history_client_(client),
207       profile_(profile),
208       visitedlink_master_(new visitedlink::VisitedLinkMaster(
209           profile, this, true)),
210       backend_loaded_(false),
211       no_db_(false) {
212   DCHECK(profile_);
213   registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED,
214                  content::Source<Profile>(profile_));
215   registrar_.Add(this, chrome::NOTIFICATION_TEMPLATE_URL_REMOVED,
216                  content::Source<Profile>(profile_));
217 }
218 
~HistoryService()219 HistoryService::~HistoryService() {
220   DCHECK(thread_checker_.CalledOnValidThread());
221   // Shutdown the backend. This does nothing if Cleanup was already invoked.
222   Cleanup();
223 }
224 
BackendLoaded()225 bool HistoryService::BackendLoaded() {
226   DCHECK(thread_checker_.CalledOnValidThread());
227   return backend_loaded_;
228 }
229 
Cleanup()230 void HistoryService::Cleanup() {
231   DCHECK(thread_checker_.CalledOnValidThread());
232   if (!thread_) {
233     // We've already cleaned up.
234     return;
235   }
236 
237   weak_ptr_factory_.InvalidateWeakPtrs();
238 
239   // Unload the backend.
240   if (history_backend_) {
241     // Get rid of the in-memory backend.
242     in_memory_backend_.reset();
243 
244     // Give the InMemoryURLIndex a chance to shutdown.
245     // NOTE: In tests, there may be no index.
246     if (in_memory_url_index_)
247       in_memory_url_index_->ShutDown();
248 
249     // The backend's destructor must run on the history thread since it is not
250     // threadsafe. So this thread must not be the last thread holding a
251     // reference to the backend, or a crash could happen.
252     //
253     // We have a reference to the history backend. There is also an extra
254     // reference held by our delegate installed in the backend, which
255     // HistoryBackend::Closing will release. This means if we scheduled a call
256     // to HistoryBackend::Closing and *then* released our backend reference,
257     // there will be a race between us and the backend's Closing function to see
258     // who is the last holder of a reference. If the backend thread's Closing
259     // manages to run before we release our backend refptr, the last reference
260     // will be held by this thread and the destructor will be called from here.
261     //
262     // Therefore, we create a closure to run the Closing operation first. This
263     // holds a reference to the backend. Then we release our reference, then we
264     // schedule the task to run. After the task runs, it will delete its
265     // reference from the history thread, ensuring everything works properly.
266     //
267     // TODO(ajwong): Cleanup HistoryBackend lifetime issues.
268     //     See http://crbug.com/99767.
269     history_backend_->AddRef();
270     base::Closure closing_task =
271         base::Bind(&HistoryBackend::Closing, history_backend_.get());
272     ScheduleTask(PRIORITY_NORMAL, closing_task);
273     closing_task.Reset();
274     HistoryBackend* raw_ptr = history_backend_.get();
275     history_backend_ = NULL;
276     thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr);
277   }
278 
279   // Delete the thread, which joins with the background thread. We defensively
280   // NULL the pointer before deleting it in case somebody tries to use it
281   // during shutdown, but this shouldn't happen.
282   base::Thread* thread = thread_;
283   thread_ = NULL;
284   delete thread;
285 }
286 
ClearCachedDataForContextID(history::ContextID context_id)287 void HistoryService::ClearCachedDataForContextID(
288     history::ContextID context_id) {
289   DCHECK(thread_checker_.CalledOnValidThread());
290   ScheduleAndForget(PRIORITY_NORMAL,
291                     &HistoryBackend::ClearCachedDataForContextID, context_id);
292 }
293 
InMemoryDatabase()294 history::URLDatabase* HistoryService::InMemoryDatabase() {
295   DCHECK(thread_checker_.CalledOnValidThread());
296   return in_memory_backend_ ? in_memory_backend_->db() : NULL;
297 }
298 
GetTypedCountForURL(const GURL & url,int * typed_count)299 bool HistoryService::GetTypedCountForURL(const GURL& url, int* typed_count) {
300   DCHECK(thread_checker_.CalledOnValidThread());
301   history::URLRow url_row;
302   if (!GetRowForURL(url, &url_row))
303     return false;
304   *typed_count = url_row.typed_count();
305   return true;
306 }
307 
GetLastVisitTimeForURL(const GURL & url,base::Time * last_visit)308 bool HistoryService::GetLastVisitTimeForURL(const GURL& url,
309                                             base::Time* last_visit) {
310   DCHECK(thread_checker_.CalledOnValidThread());
311   history::URLRow url_row;
312   if (!GetRowForURL(url, &url_row))
313     return false;
314   *last_visit = url_row.last_visit();
315   return true;
316 }
317 
GetVisitCountForURL(const GURL & url,int * visit_count)318 bool HistoryService::GetVisitCountForURL(const GURL& url, int* visit_count) {
319   DCHECK(thread_checker_.CalledOnValidThread());
320   history::URLRow url_row;
321   if (!GetRowForURL(url, &url_row))
322     return false;
323   *visit_count = url_row.visit_count();
324   return true;
325 }
326 
GetTypedUrlSyncableService() const327 history::TypedUrlSyncableService* HistoryService::GetTypedUrlSyncableService()
328     const {
329   return history_backend_->GetTypedUrlSyncableService();
330 }
331 
Shutdown()332 void HistoryService::Shutdown() {
333   DCHECK(thread_checker_.CalledOnValidThread());
334   Cleanup();
335 }
336 
SetKeywordSearchTermsForURL(const GURL & url,TemplateURLID keyword_id,const base::string16 & term)337 void HistoryService::SetKeywordSearchTermsForURL(const GURL& url,
338                                                  TemplateURLID keyword_id,
339                                                  const base::string16& term) {
340   DCHECK(thread_checker_.CalledOnValidThread());
341   ScheduleAndForget(PRIORITY_UI,
342                     &HistoryBackend::SetKeywordSearchTermsForURL,
343                     url, keyword_id, term);
344 }
345 
DeleteAllSearchTermsForKeyword(TemplateURLID keyword_id)346 void HistoryService::DeleteAllSearchTermsForKeyword(
347     TemplateURLID keyword_id) {
348   DCHECK(thread_checker_.CalledOnValidThread());
349   ScheduleAndForget(PRIORITY_UI,
350                     &HistoryBackend::DeleteAllSearchTermsForKeyword,
351                     keyword_id);
352 }
353 
GetMostRecentKeywordSearchTerms(TemplateURLID keyword_id,const base::string16 & prefix,int max_count,CancelableRequestConsumerBase * consumer,const GetMostRecentKeywordSearchTermsCallback & callback)354 HistoryService::Handle HistoryService::GetMostRecentKeywordSearchTerms(
355     TemplateURLID keyword_id,
356     const base::string16& prefix,
357     int max_count,
358     CancelableRequestConsumerBase* consumer,
359     const GetMostRecentKeywordSearchTermsCallback& callback) {
360   DCHECK(thread_checker_.CalledOnValidThread());
361   return Schedule(PRIORITY_UI, &HistoryBackend::GetMostRecentKeywordSearchTerms,
362                   consumer,
363                   new history::GetMostRecentKeywordSearchTermsRequest(callback),
364                   keyword_id, prefix, max_count);
365 }
366 
DeleteKeywordSearchTermForURL(const GURL & url)367 void HistoryService::DeleteKeywordSearchTermForURL(const GURL& url) {
368   DCHECK(thread_checker_.CalledOnValidThread());
369   ScheduleAndForget(PRIORITY_UI, &HistoryBackend::DeleteKeywordSearchTermForURL,
370                     url);
371 }
372 
DeleteMatchingURLsForKeyword(TemplateURLID keyword_id,const base::string16 & term)373 void HistoryService::DeleteMatchingURLsForKeyword(TemplateURLID keyword_id,
374                                                   const base::string16& term) {
375   DCHECK(thread_checker_.CalledOnValidThread());
376   ScheduleAndForget(PRIORITY_UI, &HistoryBackend::DeleteMatchingURLsForKeyword,
377                     keyword_id, term);
378 }
379 
URLsNoLongerBookmarked(const std::set<GURL> & urls)380 void HistoryService::URLsNoLongerBookmarked(const std::set<GURL>& urls) {
381   DCHECK(thread_checker_.CalledOnValidThread());
382   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::URLsNoLongerBookmarked,
383                     urls);
384 }
385 
ScheduleDBTask(history::HistoryDBTask * task,CancelableRequestConsumerBase * consumer)386 void HistoryService::ScheduleDBTask(history::HistoryDBTask* task,
387                                     CancelableRequestConsumerBase* consumer) {
388   DCHECK(thread_checker_.CalledOnValidThread());
389   history::HistoryDBTaskRequest* request = new history::HistoryDBTaskRequest(
390       base::Bind(&history::HistoryDBTask::DoneRunOnMainThread, task));
391   request->value = task;  // The value is the task to execute.
392   Schedule(PRIORITY_UI, &HistoryBackend::ProcessDBTask, consumer, request);
393 }
394 
QuerySegmentUsageSince(CancelableRequestConsumerBase * consumer,const Time from_time,int max_result_count,const SegmentQueryCallback & callback)395 HistoryService::Handle HistoryService::QuerySegmentUsageSince(
396     CancelableRequestConsumerBase* consumer,
397     const Time from_time,
398     int max_result_count,
399     const SegmentQueryCallback& callback) {
400   DCHECK(thread_checker_.CalledOnValidThread());
401   return Schedule(PRIORITY_UI, &HistoryBackend::QuerySegmentUsage,
402                   consumer, new history::QuerySegmentUsageRequest(callback),
403                   from_time, max_result_count);
404 }
405 
FlushForTest(const base::Closure & flushed)406 void HistoryService::FlushForTest(const base::Closure& flushed) {
407   thread_->message_loop_proxy()->PostTaskAndReply(
408       FROM_HERE, base::Bind(&base::DoNothing), flushed);
409 }
410 
SetOnBackendDestroyTask(const base::Closure & task)411 void HistoryService::SetOnBackendDestroyTask(const base::Closure& task) {
412   DCHECK(thread_checker_.CalledOnValidThread());
413   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::SetOnBackendDestroyTask,
414                     base::MessageLoop::current(), task);
415 }
416 
AddPage(const GURL & url,Time time,history::ContextID context_id,int32 page_id,const GURL & referrer,const history::RedirectList & redirects,content::PageTransition transition,history::VisitSource visit_source,bool did_replace_entry)417 void HistoryService::AddPage(const GURL& url,
418                              Time time,
419                              history::ContextID context_id,
420                              int32 page_id,
421                              const GURL& referrer,
422                              const history::RedirectList& redirects,
423                              content::PageTransition transition,
424                              history::VisitSource visit_source,
425                              bool did_replace_entry) {
426   DCHECK(thread_checker_.CalledOnValidThread());
427   AddPage(
428       history::HistoryAddPageArgs(url, time, context_id, page_id, referrer,
429                                   redirects, transition, visit_source,
430                                   did_replace_entry));
431 }
432 
AddPage(const GURL & url,base::Time time,history::VisitSource visit_source)433 void HistoryService::AddPage(const GURL& url,
434                              base::Time time,
435                              history::VisitSource visit_source) {
436   DCHECK(thread_checker_.CalledOnValidThread());
437   AddPage(
438       history::HistoryAddPageArgs(url, time, NULL, 0, GURL(),
439                                   history::RedirectList(),
440                                   content::PAGE_TRANSITION_LINK,
441                                   visit_source, false));
442 }
443 
AddPage(const history::HistoryAddPageArgs & add_page_args)444 void HistoryService::AddPage(const history::HistoryAddPageArgs& add_page_args) {
445   DCHECK(thread_checker_.CalledOnValidThread());
446   DCHECK(thread_) << "History service being called after cleanup";
447 
448   // Filter out unwanted URLs. We don't add auto-subframe URLs. They are a
449   // large part of history (think iframes for ads) and we never display them in
450   // history UI. We will still add manual subframes, which are ones the user
451   // has clicked on to get.
452   if (!CanAddURL(add_page_args.url))
453     return;
454 
455   // Add link & all redirects to visited link list.
456   if (visitedlink_master_) {
457     visitedlink_master_->AddURL(add_page_args.url);
458 
459     if (!add_page_args.redirects.empty()) {
460       // We should not be asked to add a page in the middle of a redirect chain.
461       DCHECK_EQ(add_page_args.url,
462                 add_page_args.redirects[add_page_args.redirects.size() - 1]);
463 
464       // We need the !redirects.empty() condition above since size_t is unsigned
465       // and will wrap around when we subtract one from a 0 size.
466       for (size_t i = 0; i < add_page_args.redirects.size() - 1; i++)
467         visitedlink_master_->AddURL(add_page_args.redirects[i]);
468     }
469   }
470 
471   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::AddPage, add_page_args);
472 }
473 
AddPageNoVisitForBookmark(const GURL & url,const base::string16 & title)474 void HistoryService::AddPageNoVisitForBookmark(const GURL& url,
475                                                const base::string16& title) {
476   DCHECK(thread_checker_.CalledOnValidThread());
477   if (!CanAddURL(url))
478     return;
479 
480   ScheduleAndForget(PRIORITY_NORMAL,
481                     &HistoryBackend::AddPageNoVisitForBookmark, url, title);
482 }
483 
SetPageTitle(const GURL & url,const base::string16 & title)484 void HistoryService::SetPageTitle(const GURL& url,
485                                   const base::string16& title) {
486   DCHECK(thread_checker_.CalledOnValidThread());
487   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::SetPageTitle, url, title);
488 }
489 
UpdateWithPageEndTime(history::ContextID context_id,int32 page_id,const GURL & url,Time end_ts)490 void HistoryService::UpdateWithPageEndTime(history::ContextID context_id,
491                                            int32 page_id,
492                                            const GURL& url,
493                                            Time end_ts) {
494   DCHECK(thread_checker_.CalledOnValidThread());
495   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::UpdateWithPageEndTime,
496                     context_id, page_id, url, end_ts);
497 }
498 
AddPageWithDetails(const GURL & url,const base::string16 & title,int visit_count,int typed_count,Time last_visit,bool hidden,history::VisitSource visit_source)499 void HistoryService::AddPageWithDetails(const GURL& url,
500                                         const base::string16& title,
501                                         int visit_count,
502                                         int typed_count,
503                                         Time last_visit,
504                                         bool hidden,
505                                         history::VisitSource visit_source) {
506   DCHECK(thread_checker_.CalledOnValidThread());
507   // Filter out unwanted URLs.
508   if (!CanAddURL(url))
509     return;
510 
511   // Add to the visited links system.
512   if (visitedlink_master_)
513     visitedlink_master_->AddURL(url);
514 
515   history::URLRow row(url);
516   row.set_title(title);
517   row.set_visit_count(visit_count);
518   row.set_typed_count(typed_count);
519   row.set_last_visit(last_visit);
520   row.set_hidden(hidden);
521 
522   history::URLRows rows;
523   rows.push_back(row);
524 
525   ScheduleAndForget(PRIORITY_NORMAL,
526                     &HistoryBackend::AddPagesWithDetails, rows, visit_source);
527 }
528 
AddPagesWithDetails(const history::URLRows & info,history::VisitSource visit_source)529 void HistoryService::AddPagesWithDetails(const history::URLRows& info,
530                                          history::VisitSource visit_source) {
531   DCHECK(thread_checker_.CalledOnValidThread());
532   // Add to the visited links system.
533   if (visitedlink_master_) {
534     std::vector<GURL> urls;
535     urls.reserve(info.size());
536     for (history::URLRows::const_iterator i = info.begin(); i != info.end();
537          ++i)
538       urls.push_back(i->url());
539 
540     visitedlink_master_->AddURLs(urls);
541   }
542 
543   ScheduleAndForget(PRIORITY_NORMAL,
544                     &HistoryBackend::AddPagesWithDetails, info, visit_source);
545 }
546 
GetFavicons(const std::vector<GURL> & icon_urls,int icon_types,const std::vector<int> & desired_sizes,const favicon_base::FaviconResultsCallback & callback,base::CancelableTaskTracker * tracker)547 base::CancelableTaskTracker::TaskId HistoryService::GetFavicons(
548     const std::vector<GURL>& icon_urls,
549     int icon_types,
550     const std::vector<int>& desired_sizes,
551     const favicon_base::FaviconResultsCallback& callback,
552     base::CancelableTaskTracker* tracker) {
553   DCHECK(thread_checker_.CalledOnValidThread());
554 
555   std::vector<favicon_base::FaviconRawBitmapResult>* results =
556       new std::vector<favicon_base::FaviconRawBitmapResult>();
557   return tracker->PostTaskAndReply(
558       thread_->message_loop_proxy().get(),
559       FROM_HERE,
560       base::Bind(&HistoryBackend::GetFavicons,
561                  history_backend_.get(),
562                  icon_urls,
563                  icon_types,
564                  desired_sizes,
565                  results),
566       base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
567 }
568 
GetFaviconsForURL(const GURL & page_url,int icon_types,const std::vector<int> & desired_sizes,const favicon_base::FaviconResultsCallback & callback,base::CancelableTaskTracker * tracker)569 base::CancelableTaskTracker::TaskId HistoryService::GetFaviconsForURL(
570     const GURL& page_url,
571     int icon_types,
572     const std::vector<int>& desired_sizes,
573     const favicon_base::FaviconResultsCallback& callback,
574     base::CancelableTaskTracker* tracker) {
575   DCHECK(thread_checker_.CalledOnValidThread());
576 
577   std::vector<favicon_base::FaviconRawBitmapResult>* results =
578       new std::vector<favicon_base::FaviconRawBitmapResult>();
579   return tracker->PostTaskAndReply(
580       thread_->message_loop_proxy().get(),
581       FROM_HERE,
582       base::Bind(&HistoryBackend::GetFaviconsForURL,
583                  history_backend_.get(),
584                  page_url,
585                  icon_types,
586                  desired_sizes,
587                  results),
588       base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
589 }
590 
GetLargestFaviconForURL(const GURL & page_url,const std::vector<int> & icon_types,int minimum_size_in_pixels,const favicon_base::FaviconRawBitmapCallback & callback,base::CancelableTaskTracker * tracker)591 base::CancelableTaskTracker::TaskId HistoryService::GetLargestFaviconForURL(
592     const GURL& page_url,
593     const std::vector<int>& icon_types,
594     int minimum_size_in_pixels,
595     const favicon_base::FaviconRawBitmapCallback& callback,
596     base::CancelableTaskTracker* tracker) {
597   DCHECK(thread_checker_.CalledOnValidThread());
598 
599   favicon_base::FaviconRawBitmapResult* result =
600       new favicon_base::FaviconRawBitmapResult();
601   return tracker->PostTaskAndReply(
602       thread_->message_loop_proxy().get(),
603       FROM_HERE,
604       base::Bind(&HistoryBackend::GetLargestFaviconForURL,
605                  history_backend_.get(),
606                  page_url,
607                  icon_types,
608                  minimum_size_in_pixels,
609                  result),
610       base::Bind(&RunWithFaviconResult, callback, base::Owned(result)));
611 }
612 
GetFaviconForID(favicon_base::FaviconID favicon_id,int desired_size,const favicon_base::FaviconResultsCallback & callback,base::CancelableTaskTracker * tracker)613 base::CancelableTaskTracker::TaskId HistoryService::GetFaviconForID(
614     favicon_base::FaviconID favicon_id,
615     int desired_size,
616     const favicon_base::FaviconResultsCallback& callback,
617     base::CancelableTaskTracker* tracker) {
618   DCHECK(thread_checker_.CalledOnValidThread());
619 
620   std::vector<favicon_base::FaviconRawBitmapResult>* results =
621       new std::vector<favicon_base::FaviconRawBitmapResult>();
622   return tracker->PostTaskAndReply(
623       thread_->message_loop_proxy().get(),
624       FROM_HERE,
625       base::Bind(&HistoryBackend::GetFaviconForID,
626                  history_backend_.get(),
627                  favicon_id,
628                  desired_size,
629                  results),
630       base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
631 }
632 
633 base::CancelableTaskTracker::TaskId
UpdateFaviconMappingsAndFetch(const GURL & page_url,const std::vector<GURL> & icon_urls,int icon_types,const std::vector<int> & desired_sizes,const favicon_base::FaviconResultsCallback & callback,base::CancelableTaskTracker * tracker)634 HistoryService::UpdateFaviconMappingsAndFetch(
635     const GURL& page_url,
636     const std::vector<GURL>& icon_urls,
637     int icon_types,
638     const std::vector<int>& desired_sizes,
639     const favicon_base::FaviconResultsCallback& callback,
640     base::CancelableTaskTracker* tracker) {
641   DCHECK(thread_checker_.CalledOnValidThread());
642 
643   std::vector<favicon_base::FaviconRawBitmapResult>* results =
644       new std::vector<favicon_base::FaviconRawBitmapResult>();
645   return tracker->PostTaskAndReply(
646       thread_->message_loop_proxy().get(),
647       FROM_HERE,
648       base::Bind(&HistoryBackend::UpdateFaviconMappingsAndFetch,
649                  history_backend_.get(),
650                  page_url,
651                  icon_urls,
652                  icon_types,
653                  desired_sizes,
654                  results),
655       base::Bind(&RunWithFaviconResults, callback, base::Owned(results)));
656 }
657 
MergeFavicon(const GURL & page_url,const GURL & icon_url,favicon_base::IconType icon_type,scoped_refptr<base::RefCountedMemory> bitmap_data,const gfx::Size & pixel_size)658 void HistoryService::MergeFavicon(
659     const GURL& page_url,
660     const GURL& icon_url,
661     favicon_base::IconType icon_type,
662     scoped_refptr<base::RefCountedMemory> bitmap_data,
663     const gfx::Size& pixel_size) {
664   DCHECK(thread_checker_.CalledOnValidThread());
665   if (!CanAddURL(page_url))
666     return;
667 
668   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::MergeFavicon, page_url,
669                     icon_url, icon_type, bitmap_data, pixel_size);
670 }
671 
SetFavicons(const GURL & page_url,favicon_base::IconType icon_type,const std::vector<favicon_base::FaviconRawBitmapData> & favicon_bitmap_data)672 void HistoryService::SetFavicons(
673     const GURL& page_url,
674     favicon_base::IconType icon_type,
675     const std::vector<favicon_base::FaviconRawBitmapData>&
676         favicon_bitmap_data) {
677   DCHECK(thread_checker_.CalledOnValidThread());
678   if (!CanAddURL(page_url))
679     return;
680 
681   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::SetFavicons, page_url,
682       icon_type, favicon_bitmap_data);
683 }
684 
SetFaviconsOutOfDateForPage(const GURL & page_url)685 void HistoryService::SetFaviconsOutOfDateForPage(const GURL& page_url) {
686   DCHECK(thread_checker_.CalledOnValidThread());
687   ScheduleAndForget(PRIORITY_NORMAL,
688                     &HistoryBackend::SetFaviconsOutOfDateForPage, page_url);
689 }
690 
CloneFavicons(const GURL & old_page_url,const GURL & new_page_url)691 void HistoryService::CloneFavicons(const GURL& old_page_url,
692                                    const GURL& new_page_url) {
693   DCHECK(thread_checker_.CalledOnValidThread());
694   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::CloneFavicons,
695                     old_page_url, new_page_url);
696 }
697 
SetImportedFavicons(const std::vector<ImportedFaviconUsage> & favicon_usage)698 void HistoryService::SetImportedFavicons(
699     const std::vector<ImportedFaviconUsage>& favicon_usage) {
700   DCHECK(thread_checker_.CalledOnValidThread());
701   ScheduleAndForget(PRIORITY_NORMAL,
702                     &HistoryBackend::SetImportedFavicons, favicon_usage);
703 }
704 
QueryURL(const GURL & url,bool want_visits,const QueryURLCallback & callback,base::CancelableTaskTracker * tracker)705 base::CancelableTaskTracker::TaskId HistoryService::QueryURL(
706     const GURL& url,
707     bool want_visits,
708     const QueryURLCallback& callback,
709     base::CancelableTaskTracker* tracker) {
710   DCHECK(thread_checker_.CalledOnValidThread());
711   HistoryBackend::QueryURLResult* query_url_result =
712       new HistoryBackend::QueryURLResult();
713   return tracker->PostTaskAndReply(
714       thread_->message_loop_proxy().get(),
715       FROM_HERE,
716       base::Bind(&HistoryBackend::QueryURL,
717                  history_backend_.get(),
718                  url,
719                  want_visits,
720                  base::Unretained(query_url_result)),
721       base::Bind(
722           &RunWithQueryURLResult, callback, base::Owned(query_url_result)));
723 }
724 
725 // Downloads -------------------------------------------------------------------
726 
727 // Handle creation of a download by creating an entry in the history service's
728 // 'downloads' table.
CreateDownload(const history::DownloadRow & create_info,const HistoryService::DownloadCreateCallback & callback)729 void HistoryService::CreateDownload(
730     const history::DownloadRow& create_info,
731     const HistoryService::DownloadCreateCallback& callback) {
732   DCHECK(thread_) << "History service being called after cleanup";
733   DCHECK(thread_checker_.CalledOnValidThread());
734   PostTaskAndReplyWithResult(
735       thread_->message_loop_proxy(), FROM_HERE,
736       base::Bind(&HistoryBackend::CreateDownload, history_backend_.get(),
737                  create_info),
738       callback);
739 }
740 
GetNextDownloadId(const content::DownloadIdCallback & callback)741 void HistoryService::GetNextDownloadId(
742     const content::DownloadIdCallback& callback) {
743   DCHECK(thread_) << "History service being called after cleanup";
744   DCHECK(thread_checker_.CalledOnValidThread());
745   PostTaskAndReplyWithResult(
746       thread_->message_loop_proxy(), FROM_HERE,
747       base::Bind(&HistoryBackend::GetNextDownloadId, history_backend_.get()),
748       callback);
749 }
750 
751 // Handle queries for a list of all downloads in the history database's
752 // 'downloads' table.
QueryDownloads(const DownloadQueryCallback & callback)753 void HistoryService::QueryDownloads(
754     const DownloadQueryCallback& callback) {
755   DCHECK(thread_) << "History service being called after cleanup";
756   DCHECK(thread_checker_.CalledOnValidThread());
757   std::vector<history::DownloadRow>* rows =
758     new std::vector<history::DownloadRow>();
759   scoped_ptr<std::vector<history::DownloadRow> > scoped_rows(rows);
760   // Beware! The first Bind() does not simply |scoped_rows.get()| because
761   // base::Passed(&scoped_rows) nullifies |scoped_rows|, and compilers do not
762   // guarantee that the first Bind's arguments are evaluated before the second
763   // Bind's arguments.
764   thread_->message_loop_proxy()->PostTaskAndReply(
765       FROM_HERE,
766       base::Bind(&HistoryBackend::QueryDownloads, history_backend_.get(), rows),
767       base::Bind(callback, base::Passed(&scoped_rows)));
768 }
769 
770 // Handle updates for a particular download. This is a 'fire and forget'
771 // operation, so we don't need to be called back.
UpdateDownload(const history::DownloadRow & data)772 void HistoryService::UpdateDownload(const history::DownloadRow& data) {
773   DCHECK(thread_checker_.CalledOnValidThread());
774   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::UpdateDownload, data);
775 }
776 
RemoveDownloads(const std::set<uint32> & ids)777 void HistoryService::RemoveDownloads(const std::set<uint32>& ids) {
778   DCHECK(thread_checker_.CalledOnValidThread());
779   ScheduleAndForget(PRIORITY_NORMAL,
780                     &HistoryBackend::RemoveDownloads, ids);
781 }
782 
QueryHistory(const base::string16 & text_query,const history::QueryOptions & options,CancelableRequestConsumerBase * consumer,const QueryHistoryCallback & callback)783 HistoryService::Handle HistoryService::QueryHistory(
784     const base::string16& text_query,
785     const history::QueryOptions& options,
786     CancelableRequestConsumerBase* consumer,
787     const QueryHistoryCallback& callback) {
788   DCHECK(thread_checker_.CalledOnValidThread());
789   return Schedule(PRIORITY_UI, &HistoryBackend::QueryHistory, consumer,
790                   new history::QueryHistoryRequest(callback),
791                   text_query, options);
792 }
793 
QueryRedirectsFrom(const GURL & from_url,CancelableRequestConsumerBase * consumer,const QueryRedirectsCallback & callback)794 HistoryService::Handle HistoryService::QueryRedirectsFrom(
795     const GURL& from_url,
796     CancelableRequestConsumerBase* consumer,
797     const QueryRedirectsCallback& callback) {
798   DCHECK(thread_checker_.CalledOnValidThread());
799   return Schedule(PRIORITY_UI, &HistoryBackend::QueryRedirectsFrom, consumer,
800       new history::QueryRedirectsRequest(callback), from_url);
801 }
802 
QueryRedirectsTo(const GURL & to_url,CancelableRequestConsumerBase * consumer,const QueryRedirectsCallback & callback)803 HistoryService::Handle HistoryService::QueryRedirectsTo(
804     const GURL& to_url,
805     CancelableRequestConsumerBase* consumer,
806     const QueryRedirectsCallback& callback) {
807   DCHECK(thread_checker_.CalledOnValidThread());
808   return Schedule(PRIORITY_NORMAL, &HistoryBackend::QueryRedirectsTo, consumer,
809       new history::QueryRedirectsRequest(callback), to_url);
810 }
811 
GetVisibleVisitCountToHost(const GURL & url,CancelableRequestConsumerBase * consumer,const GetVisibleVisitCountToHostCallback & callback)812 HistoryService::Handle HistoryService::GetVisibleVisitCountToHost(
813     const GURL& url,
814     CancelableRequestConsumerBase* consumer,
815     const GetVisibleVisitCountToHostCallback& callback) {
816   DCHECK(thread_checker_.CalledOnValidThread());
817   return Schedule(PRIORITY_UI, &HistoryBackend::GetVisibleVisitCountToHost,
818       consumer, new history::GetVisibleVisitCountToHostRequest(callback), url);
819 }
820 
QueryTopURLsAndRedirects(int result_count,CancelableRequestConsumerBase * consumer,const QueryTopURLsAndRedirectsCallback & callback)821 HistoryService::Handle HistoryService::QueryTopURLsAndRedirects(
822     int result_count,
823     CancelableRequestConsumerBase* consumer,
824     const QueryTopURLsAndRedirectsCallback& callback) {
825   DCHECK(thread_checker_.CalledOnValidThread());
826   return Schedule(PRIORITY_NORMAL, &HistoryBackend::QueryTopURLsAndRedirects,
827       consumer, new history::QueryTopURLsAndRedirectsRequest(callback),
828       result_count);
829 }
830 
QueryMostVisitedURLs(int result_count,int days_back,CancelableRequestConsumerBase * consumer,const QueryMostVisitedURLsCallback & callback)831 HistoryService::Handle HistoryService::QueryMostVisitedURLs(
832     int result_count,
833     int days_back,
834     CancelableRequestConsumerBase* consumer,
835     const QueryMostVisitedURLsCallback& callback) {
836   DCHECK(thread_checker_.CalledOnValidThread());
837   return Schedule(PRIORITY_NORMAL, &HistoryBackend::QueryMostVisitedURLs,
838                   consumer,
839                   new history::QueryMostVisitedURLsRequest(callback),
840                   result_count, days_back);
841 }
842 
QueryFilteredURLs(int result_count,const history::VisitFilter & filter,bool extended_info,CancelableRequestConsumerBase * consumer,const QueryFilteredURLsCallback & callback)843 HistoryService::Handle HistoryService::QueryFilteredURLs(
844     int result_count,
845     const history::VisitFilter& filter,
846     bool extended_info,
847     CancelableRequestConsumerBase* consumer,
848     const QueryFilteredURLsCallback& callback) {
849   DCHECK(thread_checker_.CalledOnValidThread());
850   return Schedule(PRIORITY_NORMAL,
851                   &HistoryBackend::QueryFilteredURLs,
852                   consumer,
853                   new history::QueryFilteredURLsRequest(callback),
854                   result_count, filter, extended_info);
855 }
856 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)857 void HistoryService::Observe(int type,
858                              const content::NotificationSource& source,
859                              const content::NotificationDetails& details) {
860   DCHECK(thread_checker_.CalledOnValidThread());
861   if (!thread_)
862     return;
863 
864   switch (type) {
865     case chrome::NOTIFICATION_HISTORY_URLS_DELETED: {
866       // Update the visited link system for deleted URLs. We will update the
867       // visited link system for added URLs as soon as we get the add
868       // notification (we don't have to wait for the backend, which allows us to
869       // be faster to update the state).
870       //
871       // For deleted URLs, we don't typically know what will be deleted since
872       // delete notifications are by time. We would also like to be more
873       // respectful of privacy and never tell the user something is gone when it
874       // isn't. Therefore, we update the delete URLs after the fact.
875       if (visitedlink_master_) {
876         content::Details<history::URLsDeletedDetails> deleted_details(details);
877 
878         if (deleted_details->all_history) {
879           visitedlink_master_->DeleteAllURLs();
880         } else {
881           URLIteratorFromURLRows iterator(deleted_details->rows);
882           visitedlink_master_->DeleteURLs(&iterator);
883         }
884       }
885       break;
886     }
887 
888     case chrome::NOTIFICATION_TEMPLATE_URL_REMOVED:
889       DeleteAllSearchTermsForKeyword(
890           *(content::Details<TemplateURLID>(details).ptr()));
891       break;
892 
893     default:
894       NOTREACHED();
895   }
896 }
897 
RebuildTable(const scoped_refptr<URLEnumerator> & enumerator)898 void HistoryService::RebuildTable(
899     const scoped_refptr<URLEnumerator>& enumerator) {
900   DCHECK(thread_checker_.CalledOnValidThread());
901   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::IterateURLs, enumerator);
902 }
903 
Init(const base::FilePath & history_dir,bool no_db)904 bool HistoryService::Init(const base::FilePath& history_dir, bool no_db) {
905   DCHECK(thread_checker_.CalledOnValidThread());
906   if (!thread_->Start()) {
907     Cleanup();
908     return false;
909   }
910 
911   history_dir_ = history_dir;
912   no_db_ = no_db;
913 
914   if (profile_) {
915     std::string languages =
916         profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
917     in_memory_url_index_.reset(new history::InMemoryURLIndex(
918         profile_, history_dir_, languages, history_client_));
919     in_memory_url_index_->Init();
920   }
921 
922   // Create the history backend.
923   scoped_refptr<HistoryBackend> backend(
924       new HistoryBackend(history_dir_,
925                          new BackendDelegate(
926                              weak_ptr_factory_.GetWeakPtr(),
927                              base::ThreadTaskRunnerHandle::Get(),
928                              profile_),
929                          history_client_));
930   history_backend_.swap(backend);
931 
932   // There may not be a profile when unit testing.
933   std::string languages;
934   if (profile_) {
935     PrefService* prefs = profile_->GetPrefs();
936     languages = prefs->GetString(prefs::kAcceptLanguages);
937   }
938   ScheduleAndForget(PRIORITY_UI, &HistoryBackend::Init, languages, no_db_);
939 
940   if (visitedlink_master_) {
941     bool result = visitedlink_master_->Init();
942     DCHECK(result);
943   }
944 
945   return true;
946 }
947 
ScheduleAutocomplete(HistoryURLProvider * provider,HistoryURLProviderParams * params)948 void HistoryService::ScheduleAutocomplete(HistoryURLProvider* provider,
949                                           HistoryURLProviderParams* params) {
950   DCHECK(thread_checker_.CalledOnValidThread());
951   ScheduleAndForget(PRIORITY_UI, &HistoryBackend::ScheduleAutocomplete,
952                     scoped_refptr<HistoryURLProvider>(provider), params);
953 }
954 
ScheduleTask(SchedulePriority priority,const base::Closure & task)955 void HistoryService::ScheduleTask(SchedulePriority priority,
956                                   const base::Closure& task) {
957   DCHECK(thread_checker_.CalledOnValidThread());
958   CHECK(thread_);
959   CHECK(thread_->message_loop());
960   // TODO(brettw): Do prioritization.
961   thread_->message_loop()->PostTask(FROM_HERE, task);
962 }
963 
964 // static
CanAddURL(const GURL & url)965 bool HistoryService::CanAddURL(const GURL& url) {
966   if (!url.is_valid())
967     return false;
968 
969   // TODO: We should allow kChromeUIScheme URLs if they have been explicitly
970   // typed.  Right now, however, these are marked as typed even when triggered
971   // by a shortcut or menu action.
972   if (url.SchemeIs(url::kJavaScriptScheme) ||
973       url.SchemeIs(content::kChromeDevToolsScheme) ||
974       url.SchemeIs(content::kChromeUIScheme) ||
975       url.SchemeIs(content::kViewSourceScheme) ||
976       url.SchemeIs(chrome::kChromeNativeScheme) ||
977       url.SchemeIs(chrome::kChromeSearchScheme) ||
978       url.SchemeIs(chrome::kDomDistillerScheme))
979     return false;
980 
981   // Allow all about: and chrome: URLs except about:blank, since the user may
982   // like to see "chrome://memory/", etc. in their history and autocomplete.
983   if (url == GURL(url::kAboutBlankURL))
984     return false;
985 
986   return true;
987 }
988 
AsWeakPtr()989 base::WeakPtr<HistoryService> HistoryService::AsWeakPtr() {
990   DCHECK(thread_checker_.CalledOnValidThread());
991   return weak_ptr_factory_.GetWeakPtr();
992 }
993 
MergeDataAndStartSyncing(syncer::ModelType type,const syncer::SyncDataList & initial_sync_data,scoped_ptr<syncer::SyncChangeProcessor> sync_processor,scoped_ptr<syncer::SyncErrorFactory> error_handler)994 syncer::SyncMergeResult HistoryService::MergeDataAndStartSyncing(
995     syncer::ModelType type,
996     const syncer::SyncDataList& initial_sync_data,
997     scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
998     scoped_ptr<syncer::SyncErrorFactory> error_handler) {
999   DCHECK(thread_checker_.CalledOnValidThread());
1000   DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
1001   delete_directive_handler_.Start(this, initial_sync_data,
1002                                   sync_processor.Pass());
1003   return syncer::SyncMergeResult(type);
1004 }
1005 
StopSyncing(syncer::ModelType type)1006 void HistoryService::StopSyncing(syncer::ModelType type) {
1007   DCHECK(thread_checker_.CalledOnValidThread());
1008   DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
1009   delete_directive_handler_.Stop();
1010 }
1011 
GetAllSyncData(syncer::ModelType type) const1012 syncer::SyncDataList HistoryService::GetAllSyncData(
1013     syncer::ModelType type) const {
1014   DCHECK(thread_checker_.CalledOnValidThread());
1015   DCHECK_EQ(type, syncer::HISTORY_DELETE_DIRECTIVES);
1016   // TODO(akalin): Keep track of existing delete directives.
1017   return syncer::SyncDataList();
1018 }
1019 
ProcessSyncChanges(const tracked_objects::Location & from_here,const syncer::SyncChangeList & change_list)1020 syncer::SyncError HistoryService::ProcessSyncChanges(
1021     const tracked_objects::Location& from_here,
1022     const syncer::SyncChangeList& change_list) {
1023   delete_directive_handler_.ProcessSyncChanges(this, change_list);
1024   return syncer::SyncError();
1025 }
1026 
ProcessLocalDeleteDirective(const sync_pb::HistoryDeleteDirectiveSpecifics & delete_directive)1027 syncer::SyncError HistoryService::ProcessLocalDeleteDirective(
1028     const sync_pb::HistoryDeleteDirectiveSpecifics& delete_directive) {
1029   DCHECK(thread_checker_.CalledOnValidThread());
1030   return delete_directive_handler_.ProcessLocalDeleteDirective(
1031       delete_directive);
1032 }
1033 
SetInMemoryBackend(scoped_ptr<history::InMemoryHistoryBackend> mem_backend)1034 void HistoryService::SetInMemoryBackend(
1035     scoped_ptr<history::InMemoryHistoryBackend> mem_backend) {
1036   DCHECK(thread_checker_.CalledOnValidThread());
1037   DCHECK(!in_memory_backend_) << "Setting mem DB twice";
1038   in_memory_backend_.reset(mem_backend.release());
1039 
1040   // The database requires additional initialization once we own it.
1041   in_memory_backend_->AttachToHistoryService(profile_);
1042 }
1043 
NotifyProfileError(sql::InitStatus init_status)1044 void HistoryService::NotifyProfileError(sql::InitStatus init_status) {
1045   DCHECK(thread_checker_.CalledOnValidThread());
1046   if (history_client_)
1047     history_client_->NotifyProfileError(init_status);
1048 }
1049 
DeleteURL(const GURL & url)1050 void HistoryService::DeleteURL(const GURL& url) {
1051   DCHECK(thread_checker_.CalledOnValidThread());
1052   // We will update the visited links when we observe the delete notifications.
1053   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::DeleteURL, url);
1054 }
1055 
DeleteURLsForTest(const std::vector<GURL> & urls)1056 void HistoryService::DeleteURLsForTest(const std::vector<GURL>& urls) {
1057   DCHECK(thread_checker_.CalledOnValidThread());
1058   // We will update the visited links when we observe the delete
1059   // notifications.
1060   ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::DeleteURLs, urls);
1061 }
1062 
ExpireHistoryBetween(const std::set<GURL> & restrict_urls,Time begin_time,Time end_time,const base::Closure & callback,base::CancelableTaskTracker * tracker)1063 void HistoryService::ExpireHistoryBetween(
1064     const std::set<GURL>& restrict_urls,
1065     Time begin_time,
1066     Time end_time,
1067     const base::Closure& callback,
1068     base::CancelableTaskTracker* tracker) {
1069   DCHECK(thread_);
1070   DCHECK(thread_checker_.CalledOnValidThread());
1071   DCHECK(history_backend_.get());
1072   tracker->PostTaskAndReply(thread_->message_loop_proxy().get(),
1073                             FROM_HERE,
1074                             base::Bind(&HistoryBackend::ExpireHistoryBetween,
1075                                        history_backend_,
1076                                        restrict_urls,
1077                                        begin_time,
1078                                        end_time),
1079                             callback);
1080 }
1081 
ExpireHistory(const std::vector<history::ExpireHistoryArgs> & expire_list,const base::Closure & callback,base::CancelableTaskTracker * tracker)1082 void HistoryService::ExpireHistory(
1083     const std::vector<history::ExpireHistoryArgs>& expire_list,
1084     const base::Closure& callback,
1085     base::CancelableTaskTracker* tracker) {
1086   DCHECK(thread_);
1087   DCHECK(thread_checker_.CalledOnValidThread());
1088   DCHECK(history_backend_.get());
1089   tracker->PostTaskAndReply(
1090       thread_->message_loop_proxy().get(),
1091       FROM_HERE,
1092       base::Bind(&HistoryBackend::ExpireHistory, history_backend_, expire_list),
1093       callback);
1094 }
1095 
ExpireLocalAndRemoteHistoryBetween(const std::set<GURL> & restrict_urls,Time begin_time,Time end_time,const base::Closure & callback,base::CancelableTaskTracker * tracker)1096 void HistoryService::ExpireLocalAndRemoteHistoryBetween(
1097     const std::set<GURL>& restrict_urls,
1098     Time begin_time,
1099     Time end_time,
1100     const base::Closure& callback,
1101     base::CancelableTaskTracker* tracker) {
1102   // TODO(dubroy): This should be factored out into a separate class that
1103   // dispatches deletions to the proper places.
1104 
1105   history::WebHistoryService* web_history =
1106       WebHistoryServiceFactory::GetForProfile(profile_);
1107   if (web_history) {
1108     // TODO(dubroy): This API does not yet support deletion of specific URLs.
1109     DCHECK(restrict_urls.empty());
1110 
1111     delete_directive_handler_.CreateDeleteDirectives(
1112         std::set<int64>(), begin_time, end_time);
1113 
1114     // Attempt online deletion from the history server, but ignore the result.
1115     // Deletion directives ensure that the results will eventually be deleted.
1116     //
1117     // TODO(davidben): |callback| should not run until this operation completes
1118     // too.
1119     web_history->ExpireHistoryBetween(
1120         restrict_urls, begin_time, end_time,
1121         base::Bind(&ExpireWebHistoryComplete));
1122   }
1123   ExpireHistoryBetween(restrict_urls, begin_time, end_time, callback, tracker);
1124 }
1125 
BroadcastNotificationsHelper(int type,scoped_ptr<history::HistoryDetails> details)1126 void HistoryService::BroadcastNotificationsHelper(
1127     int type,
1128     scoped_ptr<history::HistoryDetails> details) {
1129   DCHECK(thread_checker_.CalledOnValidThread());
1130   // TODO(evanm): this is currently necessitated by generate_profile, which
1131   // runs without a browser process. generate_profile should really create
1132   // a browser process, at which point this check can then be nuked.
1133   if (!g_browser_process)
1134     return;
1135 
1136   if (!thread_)
1137     return;
1138 
1139   // The source of all of our notifications is the profile. Note that this
1140   // pointer is NULL in unit tests.
1141   content::Source<Profile> source(profile_);
1142 
1143   // The details object just contains the pointer to the object that the
1144   // backend has allocated for us. The receiver of the notification will cast
1145   // this to the proper type.
1146   content::Details<history::HistoryDetails> det(details.get());
1147 
1148   content::NotificationService::current()->Notify(type, source, det);
1149 }
1150 
OnDBLoaded()1151 void HistoryService::OnDBLoaded() {
1152   DCHECK(thread_checker_.CalledOnValidThread());
1153   backend_loaded_ = true;
1154   content::NotificationService::current()->Notify(
1155       chrome::NOTIFICATION_HISTORY_LOADED,
1156       content::Source<Profile>(profile_),
1157       content::Details<HistoryService>(this));
1158 }
1159 
GetRowForURL(const GURL & url,history::URLRow * url_row)1160 bool HistoryService::GetRowForURL(const GURL& url, history::URLRow* url_row) {
1161   DCHECK(thread_checker_.CalledOnValidThread());
1162   history::URLDatabase* db = InMemoryDatabase();
1163   return db && (db->GetRowForURL(url, url_row) != 0);
1164 }
1165 
AddVisitDatabaseObserver(history::VisitDatabaseObserver * observer)1166 void HistoryService::AddVisitDatabaseObserver(
1167     history::VisitDatabaseObserver* observer) {
1168   DCHECK(thread_checker_.CalledOnValidThread());
1169   visit_database_observers_.AddObserver(observer);
1170 }
1171 
RemoveVisitDatabaseObserver(history::VisitDatabaseObserver * observer)1172 void HistoryService::RemoveVisitDatabaseObserver(
1173     history::VisitDatabaseObserver* observer) {
1174   DCHECK(thread_checker_.CalledOnValidThread());
1175   visit_database_observers_.RemoveObserver(observer);
1176 }
1177 
NotifyVisitDBObserversOnAddVisit(const history::BriefVisitInfo & info)1178 void HistoryService::NotifyVisitDBObserversOnAddVisit(
1179     const history::BriefVisitInfo& info) {
1180   DCHECK(thread_checker_.CalledOnValidThread());
1181   FOR_EACH_OBSERVER(history::VisitDatabaseObserver, visit_database_observers_,
1182                     OnAddVisit(info));
1183 }
1184