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