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
3// found in the LICENSE file.
4
5#include "chrome/browser/history/top_sites_backend.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/files/file_path.h"
10#include "base/memory/ref_counted.h"
11#include "base/task/cancelable_task_tracker.h"
12#include "chrome/browser/history/top_sites_database.h"
13#include "content/public/browser/browser_thread.h"
14#include "sql/connection.h"
15
16using content::BrowserThread;
17
18namespace history {
19
20TopSitesBackend::TopSitesBackend()
21    : db_(new TopSitesDatabase()) {
22}
23
24void TopSitesBackend::Init(const base::FilePath& path) {
25  db_path_ = path;
26  BrowserThread::PostTask(
27      BrowserThread::DB, FROM_HERE,
28      base::Bind(&TopSitesBackend::InitDBOnDBThread, this, path));
29}
30
31void TopSitesBackend::Shutdown() {
32  BrowserThread::PostTask(
33      BrowserThread::DB, FROM_HERE,
34      base::Bind(&TopSitesBackend::ShutdownDBOnDBThread, this));
35}
36
37void TopSitesBackend::GetMostVisitedThumbnails(
38    const GetMostVisitedThumbnailsCallback& callback,
39    base::CancelableTaskTracker* tracker) {
40  scoped_refptr<MostVisitedThumbnails> thumbnails = new MostVisitedThumbnails();
41
42  tracker->PostTaskAndReply(
43      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
44      FROM_HERE,
45      base::Bind(&TopSitesBackend::GetMostVisitedThumbnailsOnDBThread,
46                 this,
47                 thumbnails),
48      base::Bind(callback, thumbnails));
49}
50
51void TopSitesBackend::UpdateTopSites(const TopSitesDelta& delta) {
52  BrowserThread::PostTask(
53      BrowserThread::DB, FROM_HERE,
54      base::Bind(&TopSitesBackend::UpdateTopSitesOnDBThread, this, delta));
55}
56
57void TopSitesBackend::SetPageThumbnail(const MostVisitedURL& url,
58                                       int url_rank,
59                                       const Images& thumbnail) {
60  BrowserThread::PostTask(
61      BrowserThread::DB, FROM_HERE,
62      base::Bind(&TopSitesBackend::SetPageThumbnailOnDBThread, this, url,
63                 url_rank, thumbnail));
64}
65
66void TopSitesBackend::ResetDatabase() {
67  BrowserThread::PostTask(
68      BrowserThread::DB, FROM_HERE,
69      base::Bind(&TopSitesBackend::ResetDatabaseOnDBThread, this, db_path_));
70}
71
72void TopSitesBackend::DoEmptyRequest(const base::Closure& reply,
73                                     base::CancelableTaskTracker* tracker) {
74  tracker->PostTaskAndReply(
75      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
76      FROM_HERE,
77      base::Bind(&base::DoNothing),
78      reply);
79}
80
81TopSitesBackend::~TopSitesBackend() {
82  DCHECK(!db_);  // Shutdown should have happened first (which results in
83                 // nulling out db).
84}
85
86void TopSitesBackend::InitDBOnDBThread(const base::FilePath& path) {
87  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
88  if (!db_->Init(path)) {
89    LOG(ERROR) << "Failed to initialize database.";
90    db_.reset();
91  }
92}
93
94void TopSitesBackend::ShutdownDBOnDBThread() {
95  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
96  db_.reset();
97}
98
99void TopSitesBackend::GetMostVisitedThumbnailsOnDBThread(
100    scoped_refptr<MostVisitedThumbnails> thumbnails) {
101  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
102
103  if (db_) {
104    db_->GetPageThumbnails(&(thumbnails->most_visited),
105                           &(thumbnails->url_to_images_map));
106  }
107}
108
109void TopSitesBackend::UpdateTopSitesOnDBThread(const TopSitesDelta& delta) {
110  if (!db_)
111    return;
112
113  for (size_t i = 0; i < delta.deleted.size(); ++i)
114    db_->RemoveURL(delta.deleted[i]);
115
116  for (size_t i = 0; i < delta.added.size(); ++i)
117    db_->SetPageThumbnail(delta.added[i].url, delta.added[i].rank, Images());
118
119  for (size_t i = 0; i < delta.moved.size(); ++i)
120    db_->UpdatePageRank(delta.moved[i].url, delta.moved[i].rank);
121}
122
123void TopSitesBackend::SetPageThumbnailOnDBThread(const MostVisitedURL& url,
124                                                 int url_rank,
125                                                 const Images& thumbnail) {
126  if (!db_)
127    return;
128
129  db_->SetPageThumbnail(url, url_rank, thumbnail);
130}
131
132void TopSitesBackend::ResetDatabaseOnDBThread(const base::FilePath& file_path) {
133  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
134  db_.reset(NULL);
135  sql::Connection::Delete(db_path_);
136  db_.reset(new TopSitesDatabase());
137  InitDBOnDBThread(db_path_);
138}
139
140}  // namespace history
141