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_URL_DATABASE_H_
6#define CHROME_BROWSER_HISTORY_URL_DATABASE_H_
7
8#include "base/basictypes.h"
9#include "chrome/browser/history/history_types.h"
10#include "chrome/browser/history/query_parser.h"
11#include "chrome/browser/search_engines/template_url_id.h"
12#include "sql/statement.h"
13
14class GURL;
15
16namespace sql {
17class Connection;
18}
19
20namespace history {
21
22class VisitDatabase;  // For friend statement.
23
24// Encapsulates an SQL database that holds URL info.  This is a subset of the
25// full history data.  We split this class' functionality out from the larger
26// HistoryDatabase class to support maintaining separate databases of URLs with
27// different capabilities (for example, in-memory, or archived).
28//
29// This is refcounted to support calling InvokeLater() with some of its methods
30// (necessary to maintain ordering of DB operations).
31class URLDatabase {
32 public:
33  // Must call CreateURLTable() and CreateURLIndexes() before using to make
34  // sure the database is initialized.
35  URLDatabase();
36
37  // This object must be destroyed on the thread where all accesses are
38  // happening to avoid thread-safety problems.
39  virtual ~URLDatabase();
40
41  // Converts a GURL to a string used in the history database. We plan to
42  // do more complex operations than just getting the spec out involving
43  // punycode, so this function should be used instead of url.spec() when
44  // interacting with the database.
45  //
46  // TODO(brettw) this should be moved out of the public section and the
47  // entire public HistoryDatabase interface should use GURL. This should
48  // also probably return a string instead since that is what the DB uses
49  // internally and we can avoid the extra conversion.
50  static std::string GURLToDatabaseURL(const GURL& url);
51
52  // URL table functions -------------------------------------------------------
53
54  // Looks up a url given an id. Fills info with the data. Returns true on
55  // success and false otherwise.
56  bool GetURLRow(URLID url_id, URLRow* info);
57
58  // Looks up all urls that were typed in manually. Fills info with the data.
59  // Returns true on success and false otherwise.
60  bool GetAllTypedUrls(URLRows* urls);
61
62  // Looks up the given URL and if it exists, fills the given pointers with the
63  // associated info and returns the ID of that URL. If the info pointer is
64  // NULL, no information about the URL will be filled in, only the ID will be
65  // returned. Returns 0 if the URL was not found.
66  URLID GetRowForURL(const GURL& url, URLRow* info);
67
68  // Given an already-existing row in the URL table, updates that URL's stats.
69  // This can not change the URL.  Returns true on success.
70  //
71  // This will NOT update the title used for full text indexing. If you are
72  // setting the title, call SetPageIndexedData with the new title.
73  bool UpdateURLRow(URLID url_id, const URLRow& info);
74
75  // Adds a line to the URL database with the given information and returns the
76  // row ID. A row with the given URL must not exist. Returns 0 on error.
77  //
78  // This does NOT add a row to the full text search database. Use
79  // HistoryDatabase::SetPageIndexedData to do this.
80  URLID AddURL(const URLRow& info) {
81    return AddURLInternal(info, false);
82  }
83
84  // Delete the row of the corresponding URL. Only the row in the URL table
85  // will be deleted, not any other data that may refer to it. Returns true if
86  // the row existed and was deleted.
87  bool DeleteURLRow(URLID id);
88
89  // URL mass-deleting ---------------------------------------------------------
90
91  // Begins the mass-deleting operation by creating a temporary URL table.
92  // The caller than adds the URLs it wants to preseve to the temporary table,
93  // and then deletes everything else by calling CommitTemporaryURLTable().
94  // Returns true on success.
95  bool CreateTemporaryURLTable();
96
97  // Adds a row to the temporary URL table. This must be called between
98  // CreateTemporaryURLTable() and CommitTemporaryURLTable() (see those for more
99  // info). The ID of the URL will change in the temporary table, so the new ID
100  // is returned. Returns 0 on failure.
101  URLID AddTemporaryURL(const URLRow& row) {
102    return AddURLInternal(row, true);
103  }
104
105  // Ends the mass-deleting by replacing the original URL table with the
106  // temporary one created in CreateTemporaryURLTable. Returns true on success.
107  //
108  // This function does not create the supplimentary indices. It is virtual so
109  // that the main history database can provide this additional behavior.
110  virtual bool CommitTemporaryURLTable();
111
112  // Enumeration ---------------------------------------------------------------
113
114  // A basic enumerator to enumerate urls database.
115  class URLEnumeratorBase {
116   public:
117    URLEnumeratorBase();
118    virtual ~URLEnumeratorBase();
119
120   private:
121    friend class URLDatabase;
122
123    bool initialized_;
124    sql::Statement statement_;
125
126    DISALLOW_COPY_AND_ASSIGN(URLEnumeratorBase);
127  };
128
129  // A basic enumerator to enumerate urls
130  class URLEnumerator : public URLEnumeratorBase {
131   public:
132    URLEnumerator();
133
134    // Retreives the next url. Returns false if no more urls are available
135    bool GetNextURL(history::URLRow* r);
136
137   private:
138    DISALLOW_COPY_AND_ASSIGN(URLEnumerator);
139  };
140
141  // Initializes the given enumerator to enumerator all URLs in the database.
142  bool InitURLEnumeratorForEverything(URLEnumerator* enumerator);
143
144  // Initializes the given enumerator to enumerator all URLs in the database
145  // that are historically significant: ones having been visited within 3 days,
146  // having their URL manually typed more than once, or having been visited
147  // more than 3 times.
148  bool InitURLEnumeratorForSignificant(URLEnumerator* enumerator);
149
150  // Favicons ------------------------------------------------------------------
151
152  // Autocomplete --------------------------------------------------------------
153
154  // Fills the given array with URLs matching the given prefix.  They will be
155  // sorted by typed count, then by visit count, then by visit date (most recent
156  // first) up to the given maximum number.  If |typed_only| is true, only urls
157  // that have been typed once are returned.  For caller convenience, returns
158  // whether any results were found.
159  bool AutocompleteForPrefix(const std::string& prefix,
160                             size_t max_results,
161                             bool typed_only,
162                             URLRows* results);
163
164  // Returns true if the database holds some past typed navigation to a URL on
165  // the provided hostname.
166  bool IsTypedHost(const std::string& host);
167
168  // Tries to find the shortest URL beginning with |base| that strictly
169  // prefixes |url|, and has minimum visit_ and typed_counts as specified.
170  // If found, fills in |info| and returns true; otherwise returns false,
171  // leaving |info| unchanged.
172  // We allow matches of exactly |base| iff |allow_base| is true.
173  bool FindShortestURLFromBase(const std::string& base,
174                               const std::string& url,
175                               int min_visits,
176                               int min_typed,
177                               bool allow_base,
178                               history::URLRow* info);
179
180  // History search ------------------------------------------------------------
181
182  // Performs a brute force search over the database to find any URLs or titles
183  // which match the |query| string.  Returns any matches in |results|.
184  bool GetTextMatches(const base::string16& query, URLRows* results);
185
186  // Keyword Search Terms ------------------------------------------------------
187
188  // Sets the search terms for the specified url/keyword pair.
189  bool SetKeywordSearchTermsForURL(URLID url_id,
190                                   TemplateURLID keyword_id,
191                                   const base::string16& term);
192
193  // Looks up a keyword search term given a url id. Returns all the search terms
194  // in |rows|. Returns true on success.
195  bool GetKeywordSearchTermRow(URLID url_id, KeywordSearchTermRow* row);
196
197  // Looks up all keyword search terms given a term, Fills the rows with data.
198  // Returns true on success and false otherwise.
199  bool GetKeywordSearchTermRows(const base::string16& term,
200                                std::vector<KeywordSearchTermRow>* rows);
201
202  // Deletes all search terms for the specified keyword that have been added by
203  // way of SetKeywordSearchTermsForURL.
204  void DeleteAllSearchTermsForKeyword(TemplateURLID keyword_id);
205
206  // Returns up to max_count of the most recent search terms for the specified
207  // keyword.
208  void GetMostRecentKeywordSearchTerms(
209      TemplateURLID keyword_id,
210      const base::string16& prefix,
211      int max_count,
212      std::vector<KeywordSearchTermVisit>* matches);
213
214  // Deletes all searches matching |term|.
215  bool DeleteKeywordSearchTerm(const base::string16& term);
216
217  // Deletes any search corresponding to |url_id|.
218  bool DeleteKeywordSearchTermForURL(URLID url_id);
219
220  // Migration -----------------------------------------------------------------
221
222  // Do to a bug we were setting the favicon of about:blank. This forces
223  // about:blank to have no icon or title. Returns true on success, false if
224  // the favicon couldn't be updated.
225  bool MigrateFromVersion11ToVersion12();
226
227 protected:
228  friend class VisitDatabase;
229
230  // See HISTORY_URL_ROW_FIELDS below.
231  static const char kURLRowFields[];
232
233  // The number of fiends in kURLRowFields. If callers need additional
234  // fields, they can add their 0-based index to this value to get the index of
235  // fields following kURLRowFields.
236  static const int kNumURLRowFields;
237
238  // Drops the starred_id column from urls, returning true on success. This does
239  // nothing (and returns true) if the urls doesn't contain the starred_id
240  // column.
241  bool DropStarredIDFromURLs();
242
243  // Initialization functions. The indexing functions are separate from the
244  // table creation functions so the in-memory database and the temporary tables
245  // used when clearing history can populate the table and then create the
246  // index, which is faster than the reverse.
247  //
248  // is_temporary is false when generating the "regular" URLs table. The expirer
249  // sets this to true to generate the  temporary table, which will have a
250  // different name but the same schema.
251  bool CreateURLTable(bool is_temporary);
252  // We have two tiers of indices for the URL table. The main tier is used by
253  // all URL databases, and is an index over the URL itself.
254  bool CreateMainURLIndex();
255
256  // Ensures the keyword search terms table exists.
257  bool InitKeywordSearchTermsTable();
258
259  // Creates the indices used for keyword search terms.
260  bool CreateKeywordSearchTermsIndices();
261
262  // Deletes the keyword search terms table.
263  bool DropKeywordSearchTermsTable();
264
265  // Inserts the given URL row into the URLs table, using the regular table
266  // if is_temporary is false, or the temporary URL table if is temporary is
267  // true. The temporary table may only be used in between
268  // CreateTemporaryURLTable() and CommitTemporaryURLTable().
269  URLID AddURLInternal(const URLRow& info, bool is_temporary);
270
271  // Convenience to fill a history::URLRow. Must be in sync with the fields in
272  // kHistoryURLRowFields.
273  static void FillURLRow(sql::Statement& s, URLRow* i);
274
275  // Returns the database for the functions in this interface. The decendent of
276  // this class implements these functions to return its objects.
277  virtual sql::Connection& GetDB() = 0;
278
279 private:
280  // True if InitKeywordSearchTermsTable() has been invoked. Not all subclasses
281  // have keyword search terms.
282  bool has_keyword_search_terms_;
283
284  QueryParser query_parser_;
285
286  DISALLOW_COPY_AND_ASSIGN(URLDatabase);
287};
288
289// The fields and order expected by FillURLRow(). ID is guaranteed to be first
290// so that DISTINCT can be prepended to get distinct URLs.
291//
292// This is available BOTH as a macro and a static string (kURLRowFields). Use
293// the macro if you want to put this in the middle of an otherwise constant
294// string, it will save time doing string appends. If you have to build a SQL
295// string dynamically anyway, use the constant, it will save space.
296#define HISTORY_URL_ROW_FIELDS \
297    " urls.id, urls.url, urls.title, urls.visit_count, urls.typed_count, " \
298    "urls.last_visit_time, urls.hidden "
299
300}  // namespace history
301
302#endif  // CHROME_BROWSER_HISTORY_URL_DATABASE_H_
303