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#ifndef CHROME_BROWSER_HISTORY_ANDROID_ANDROID_PROVIDER_BACKEND_H_
6#define CHROME_BROWSER_HISTORY_ANDROID_ANDROID_PROVIDER_BACKEND_H_
7
8#include <set>
9
10#include "base/containers/hash_tables.h"
11#include "base/files/file_path.h"
12#include "base/gtest_prod_util.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/scoped_vector.h"
16#include "chrome/browser/history/android/android_cache_database.h"
17#include "chrome/browser/history/android/android_history_types.h"
18#include "chrome/browser/history/android/sql_handler.h"
19#include "chrome/browser/history/history_backend.h"
20#include "chrome/browser/history/history_notifications.h"
21#include "sql/statement.h"
22#include "sql/transaction.h"
23
24namespace history {
25
26class AndroidProviderBackend;
27class AndroidURLsSQLHandler;
28class HistoryClient;
29class HistoryDatabase;
30class ThumbnailDatabase;
31
32// This class provides the query/insert/update/remove methods to implement
33// android.provider.Browser.BookmarkColumns and
34// android.provider.Browser.SearchColumns API.
35//
36// When used it:
37// a. The android_urls table is created in history database if it doesn't
38//    exists.
39// b. The android_cache database is created.
40// c. The bookmark_cache table is created.
41//
42// Android_urls and android_cache database is only updated before the related
43// methods are accessed. A data change will not triger the update.
44//
45// The android_cache database is deleted when shutdown.
46class AndroidProviderBackend {
47 public:
48  AndroidProviderBackend(const base::FilePath& cache_db_name,
49                         HistoryDatabase* history_db,
50                         ThumbnailDatabase* thumbnail_db,
51                         HistoryClient* history_client_,
52                         HistoryBackend::Delegate* delegate);
53
54  ~AndroidProviderBackend();
55
56  // Bookmarks ----------------------------------------------------------------
57  //
58  // Runs the given query and returns the result on success, NULL on error or
59  // the |projections| is empty.
60  //
61  // |projections| is the vector of the result columns.
62  // |selection| is the SQL WHERE clause without 'WHERE'.
63  // |selection_args| is the arguments for WHERE clause.
64  // |sort_order| is the SQL ORDER clause.
65  AndroidStatement* QueryHistoryAndBookmarks(
66      const std::vector<HistoryAndBookmarkRow::ColumnID>& projections,
67      const std::string& selection,
68      const std::vector<base::string16>& selection_args,
69      const std::string& sort_order);
70
71  // Runs the given update and returns the number of the updated rows in
72  // |update_count| and return true on success, false on error.
73  //
74  // |row| is the value to update.
75  // |selection| is the SQL WHERE clause without 'WHERE'.
76  // |selection_args| is the arguments for the WHERE clause.
77  bool UpdateHistoryAndBookmarks(
78      const HistoryAndBookmarkRow& row,
79      const std::string& selection,
80      const std::vector<base::string16>& selection_args,
81      int* update_count);
82
83  // Inserts the given values and returns the URLID of the inserted row.
84  AndroidURLID InsertHistoryAndBookmark(const HistoryAndBookmarkRow& values);
85
86  // Deletes the specified rows and returns the number of the deleted rows in
87  // |deleted_count|.
88  // |selection| is the SQL WHERE clause without 'WHERE'.
89  // |selection_args| is the arguments for the WHERE clause.
90  //
91  // if |selection| is empty all history and bookmarks are deleted.
92  bool DeleteHistoryAndBookmarks(
93      const std::string& selection,
94      const std::vector<base::string16>& selection_args,
95      int* deleted_count);
96
97  // Deletes the matched history, returns true on success, false on error.
98  // The number of deleted row is returned in |deleted_count|.
99  // The url row is kept and the visit count is reset if the matched url
100  // is bookmarked.
101  bool DeleteHistory(const std::string& selection,
102                     const std::vector<base::string16>& selection_args,
103                     int* deleted_count);
104
105  // SearchTerms --------------------------------------------------------------
106  //
107  // Returns the result of the given query.
108  // |projections| specifies the result columns, can not be empty, otherwise
109  // NULL is returned.
110  // |selection| is the SQL WHERE clause without 'WHERE'.
111  // |selection_args| is the arguments for WHERE clause.
112  // |sort_order| the SQL ORDER clause.
113  AndroidStatement* QuerySearchTerms(
114      const std::vector<SearchRow::ColumnID>& projections,
115      const std::string& selection,
116      const std::vector<base::string16>& selection_args,
117      const std::string& sort_order);
118
119  // Runs the given update and returns the number of updated rows in
120  // |update_count| and return true, false returned if there is any error.
121  //
122  // |row| is the value need to update.
123  // |selection| is the SQL WHERE clause without 'WHERE'.
124  // |selection_args| is the arguments for WHERE clause.
125  bool UpdateSearchTerms(const SearchRow& row,
126                         const std::string& selection,
127                         const std::vector<base::string16>& selection_args,
128                         int* update_count);
129
130  // Inserts the given valus and return the SearchTermID of inserted row.
131  SearchTermID InsertSearchTerm(const SearchRow& values);
132
133  // Deletes the matched rows and the number of deleted rows is returned in
134  // |deleted_count|.
135  // |selection| is the SQL WHERE clause without 'WHERE'.
136  // |selection_args| is the arguments for WHERE clause.
137  //
138  // if |selection| is empty all search be deleted.
139  bool DeleteSearchTerms(const std::string& selection,
140                         const std::vector<base::string16>& selection_args,
141                         int * deleted_count);
142
143 private:
144  friend class AndroidProviderBackendTest;
145
146  FRIEND_TEST_ALL_PREFIXES(AndroidProviderBackendTest, UpdateTables);
147  FRIEND_TEST_ALL_PREFIXES(AndroidProviderBackendTest, UpdateSearchTermTable);
148
149  class HistoryNotifications {
150   public:
151    HistoryNotifications();
152    ~HistoryNotifications();
153
154    void PushBack(int type, scoped_ptr<HistoryDetails> detail);
155    int PopBackType();
156    scoped_ptr<HistoryDetails> PopBackDetails();
157
158    bool empty() const { return types_.empty(); }
159
160   private:
161    std::vector<int> types_;
162    ScopedVector<HistoryDetails> details_;
163
164    DISALLOW_COPY_AND_ASSIGN(HistoryNotifications);
165  };
166
167  // The scoped transaction for AndroidProviderBackend.
168  //
169  // The new transactions are started automatically in both history and
170  // thumbnail database and could be a nesting transaction, if so, rolling back
171  // of this transaction will cause the exsting and subsequent nesting
172  // transactions failed.
173  //
174  // Commit() is used to commit the transaction, otherwise the transaction will
175  // be rolled back when the object is out of scope. This transaction could
176  // failed even the commit() is called if it is in a transaction that has been
177  // rolled back or the subsequent transaction in the same outermost
178  // transaction would be rolled back latter.
179  //
180  class ScopedTransaction {
181   public:
182    ScopedTransaction(HistoryDatabase* history_db,
183                      ThumbnailDatabase* thumbnail_db);
184    ~ScopedTransaction();
185
186    // Commit the transaction.
187    void Commit();
188
189   private:
190    HistoryDatabase* history_db_;
191    ThumbnailDatabase* thumbnail_db_;
192    // Whether the transaction was committed.
193    bool committed_;
194    // The count of the nested transaction in history database.
195    const int history_transaction_nesting_;
196    // The count of the nested transaction in thumbnail database.
197    const int thumbnail_transaction_nesting_;
198
199    DISALLOW_COPY_AND_ASSIGN(ScopedTransaction);
200  };
201
202  // Runs the given update and returns the number of updated rows in
203  // |update_count| and return true on success, false on error.
204  //
205  // The notifications are returned in |notifications| and the ownership of them
206  // is transfered to caller.
207  //
208  // |row| is the value to update.
209  // |selection| is the SQL WHERE clause without 'WHERE'.
210  // |selection_args| is the arguments for the WHERE clause.
211  bool UpdateHistoryAndBookmarks(const HistoryAndBookmarkRow& row,
212                       const std::string& selection,
213                       const std::vector<base::string16>& selection_args,
214                       int* update_count,
215                       HistoryNotifications* notifications);
216
217  // Inserts the given values and returns the URLID of the inserted row.
218  // The notifications are returned in |notifications| and the ownership of them
219  // is transfered to caller.
220  // The EnsureInitializedAndUpdated() will not be invoked if the
221  // |ensure_initialized_and_updated| is false.
222  AndroidURLID InsertHistoryAndBookmark(const HistoryAndBookmarkRow& values,
223                                        bool ensure_initialized_and_updated,
224                                        HistoryNotifications* notifications);
225
226  // Deletes the specified rows and returns the number of the deleted rows in
227  // |deleted_count|.
228  // |selection| is the SQL WHERE clause without 'WHERE'.
229  // |selection_args| is the arguments for the WHERE clause.
230  //
231  // The notifications are returned in |notifications| and the ownership of them
232  // is transfered to the caller.
233  // if |selection| is empty all history and bookmarks are deleted.
234  bool DeleteHistoryAndBookmarks(
235      const std::string& selection,
236      const std::vector<base::string16>& selection_args,
237      int* deleted_count,
238      HistoryNotifications* notifications);
239
240  // Deletes the matched history, returns true on success, false on error.
241  // The number of deleted row is returned in |deleted_count|.
242  // The notifications are returned in |notifications| and the ownership of them
243  // is transfered to caller.
244  // The url row is kept and the visit is reset if the matched url is
245  // bookmarked.
246  bool DeleteHistory(const std::string& selection,
247                     const std::vector<base::string16>& selection_args,
248                     int* deleted_count,
249                     HistoryNotifications* notifications);
250
251  // Initializes and updates tables if necessary.
252  bool EnsureInitializedAndUpdated();
253
254  // Initializes AndroidProviderBackend.
255  bool Init();
256
257  // Update android_urls and bookmark_cache table if it is necessary.
258  bool UpdateTables();
259
260  // Update the android_urls and bookmark_cache for visited urls.
261  bool UpdateVisitedURLs();
262
263  // Update the android_urls for removed urls.
264  bool UpdateRemovedURLs();
265
266  // Update the bookmark_cache table with bookmarks.
267  bool UpdateBookmarks();
268
269  // Update the bookmark_cache table for favicon.
270  bool UpdateFavicon();
271
272  // Update the search_term table
273  bool UpdateSearchTermTable();
274
275  // Append the specified result columns in |projections| to the given
276  // |result_column|.
277  // To support the lazy binding, the index of favicon column will be
278  // returned if it exists, otherwise returns -1.
279  int AppendBookmarkResultColumn(
280      const std::vector<HistoryAndBookmarkRow::ColumnID>& projections,
281      std::string* result_column);
282
283  // Append the specified search result columns in |projections| to the given
284  // |result_column|.
285  void AppendSearchResultColumn(
286      const std::vector<SearchRow::ColumnID>& projections,
287      std::string* result_column);
288
289  // Runs the given query on history_bookmark virtual table and returns true if
290  // succeeds, the selected URLID and url are returned in |rows|.
291  bool GetSelectedURLs(const std::string& selection,
292                       const std::vector<base::string16>& selection_args,
293                       TableIDRows* rows);
294
295  // Runs the given query on search_terms table and returns true on success,
296  // The selected search term are returned in |rows|.
297  typedef std::vector<base::string16> SearchTerms;
298  bool GetSelectedSearchTerms(const std::string& selection,
299                              const std::vector<base::string16>& selection_args,
300                              SearchTerms* rows);
301
302  // Simulates update url by deleting the previous URL and creating a new one.
303  // Return true on success.
304  bool SimulateUpdateURL(const HistoryAndBookmarkRow& row,
305                         const TableIDRows& ids,
306                         HistoryNotifications* notifications);
307
308  // Query bookmark without sync the tables. It should be used after syncing
309  // tables.
310  AndroidStatement* QueryHistoryAndBookmarksInternal(
311      const std::vector<HistoryAndBookmarkRow::ColumnID>& projections,
312      const std::string& selection,
313      const std::vector<base::string16>& selection_args,
314      const std::string& sort_order);
315
316  // Delete the given urls' history, returns true on success, or false on error.
317  // If |delete_bookmarks| is set, the bookmarks are deleted as well.
318  // The notifications are returned in |notifications| and the ownership of them
319  // is transfered to caller.
320  bool DeleteHistoryInternal(const TableIDRows& urls,
321                             bool delete_bookmarks,
322                             HistoryNotifications* notifications);
323
324  // Broadcasts |notifications|.  Broadcasting takes ownership of the
325  // notifications, so on return |notifications| will be empty.
326  void BroadcastNotifications(HistoryNotifications* notifications);
327
328  // Add the search term from the given |values|. It will add the values.url()
329  // in the urls table if it doesn't exist, insert visit in the visits table,
330  // also add keyword in keyword_search_term.
331  bool AddSearchTerm(const SearchRow& values);
332
333  // SQLHandlers for different tables.
334  scoped_ptr<SQLHandler> urls_handler_;
335  scoped_ptr<SQLHandler> visit_handler_;
336  scoped_ptr<SQLHandler> android_urls_handler_;
337  scoped_ptr<SQLHandler> favicon_handler_;
338  scoped_ptr<SQLHandler> bookmark_model_handler_;
339
340  // The vector of all handlers
341  std::vector<SQLHandler*> sql_handlers_;
342
343  // Android cache database filename.
344  const base::FilePath android_cache_db_filename_;
345
346  // The history db's connection.
347  sql::Connection* db_;
348
349  HistoryDatabase* history_db_;
350
351  ThumbnailDatabase* thumbnail_db_;
352
353  HistoryClient* history_client_;
354
355  // Whether AndroidProviderBackend has been initialized.
356  bool initialized_;
357
358  HistoryBackend::Delegate* delegate_;
359
360  DISALLOW_COPY_AND_ASSIGN(AndroidProviderBackend);
361};
362
363}  // namespace history
364
365#endif  // CHROME_BROWSER_HISTORY_ANDROID_ANDROID_PROVIDER_BACKEND_H_
366