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_HISTORY_DATABASE_H_
6#define CHROME_BROWSER_HISTORY_HISTORY_DATABASE_H_
7#pragma once
8
9#include "app/sql/connection.h"
10#include "app/sql/init_status.h"
11#include "app/sql/meta_table.h"
12#include "build/build_config.h"
13#include "chrome/browser/history/download_database.h"
14#include "chrome/browser/history/history_types.h"
15#include "chrome/browser/history/starred_url_database.h"
16#include "chrome/browser/history/url_database.h"
17#include "chrome/browser/history/visit_database.h"
18#include "chrome/browser/history/visitsegment_database.h"
19
20class FilePath;
21
22namespace history {
23
24// Forward declaration for the temporary migration code in Init().
25class TextDatabaseManager;
26
27// Encapsulates the SQL connection for the history database. This class holds
28// the database connection and has methods the history system (including full
29// text search) uses for writing and retrieving information.
30//
31// We try to keep most logic out of the history database; this should be seen
32// as the storage interface. Logic for manipulating this storage layer should
33// be in HistoryBackend.cc.
34class HistoryDatabase : public DownloadDatabase,
35  // TODO(sky): See if we can nuke StarredURLDatabase and just create on the
36  // stack for migration. Then HistoryDatabase would directly descend from
37  // URLDatabase.
38                        public StarredURLDatabase,
39                        public VisitDatabase,
40                        public VisitSegmentDatabase {
41 public:
42  // A simple class for scoping a history database transaction. This does not
43  // support rollback since the history database doesn't, either.
44  class TransactionScoper {
45   public:
46    explicit TransactionScoper(HistoryDatabase* db) : db_(db) {
47      db_->BeginTransaction();
48    }
49    ~TransactionScoper() {
50      db_->CommitTransaction();
51    }
52   private:
53    HistoryDatabase* db_;
54  };
55
56  // Must call Init() to complete construction. Although it can be created on
57  // any thread, it must be destructed on the history thread for proper
58  // database cleanup.
59  HistoryDatabase();
60
61  virtual ~HistoryDatabase();
62
63  // Must call this function to complete initialization. Will return true on
64  // success. On false, no other function should be called. You may want to call
65  // BeginExclusiveMode after this when you are ready.
66  sql::InitStatus Init(const FilePath& history_name,
67                       const FilePath& tmp_bookmarks_path);
68
69  // Call to set the mode on the database to exclusive. The default locking mode
70  // is "normal" but we want to run in exclusive mode for slightly better
71  // performance since we know nobody else is using the database. This is
72  // separate from Init() since the in-memory database attaches to slurp the
73  // data out, and this can't happen in exclusive mode.
74  void BeginExclusiveMode();
75
76  // Returns the current version that we will generate history databases with.
77  static int GetCurrentVersion();
78
79  // Transactions on the history database. Use the Transaction object above
80  // for most work instead of these directly. We support nested transactions
81  // and only commit when the outermost transaction is committed. This means
82  // that it is impossible to rollback a specific transaction. We could roll
83  // back the outermost transaction if any inner one is rolled back, but it
84  // turns out we don't really need this type of integrity for the history
85  // database, so we just don't support it.
86  void BeginTransaction();
87  void CommitTransaction();
88  int transaction_nesting() const {  // for debugging and assertion purposes
89    return db_.transaction_nesting();
90  }
91
92  // Drops all tables except the URL, and download tables, and recreates them
93  // from scratch. This is done to rapidly clean up stuff when deleting all
94  // history. It is faster and less likely to have problems that deleting all
95  // rows in the tables.
96  //
97  // We don't delete the downloads table, since there may be in progress
98  // downloads. We handle the download history clean up separately in:
99  // DownloadManager::RemoveDownloadsFromHistoryBetween.
100  //
101  // Returns true on success. On failure, the caller should assume that the
102  // database is invalid. There could have been an error recreating a table.
103  // This should be treated the same as an init failure, and the database
104  // should not be used any more.
105  //
106  // This will also recreate the supplementary URL indices, since these
107  // indices won't be created automatically when using the temporary URL
108  // table (what the caller does right before calling this).
109  bool RecreateAllTablesButURL();
110
111  // Vacuums the database. This will cause sqlite to defragment and collect
112  // unused space in the file. It can be VERY SLOW.
113  void Vacuum();
114
115  // Returns true if the history backend should erase the full text search
116  // and archived history files as part of version 16 -> 17 migration. The
117  // time format changed in this revision, and these files would be much slower
118  // to migrate. Since the data is less important, they should be deleted.
119  //
120  // This flag will be valid after Init() is called. It will always be false
121  // when running on Windows.
122  bool needs_version_17_migration() const {
123    return needs_version_17_migration_;
124  }
125
126  // Marks the database as no longer needing migration.
127  void ThumbnailMigrationDone();
128
129  // Returns true if thumbnails needs to be migrated.
130  bool GetNeedsThumbnailMigration();
131
132  // Visit table functions ----------------------------------------------------
133
134  // Update the segment id of a visit. Return true on success.
135  bool SetSegmentID(VisitID visit_id, SegmentID segment_id);
136
137  // Query the segment ID for the provided visit. Return 0 on failure or if the
138  // visit id wasn't found.
139  SegmentID GetSegmentID(VisitID visit_id);
140
141  // Retrieves/Updates early expiration threshold, which specifies the earliest
142  // known point in history that may possibly to contain visits suitable for
143  // early expiration (AUTO_SUBFRAMES).
144  virtual base::Time GetEarlyExpirationThreshold();
145  virtual void UpdateEarlyExpirationThreshold(base::Time threshold);
146
147 private:
148  FRIEND_TEST_ALL_PREFIXES(IconMappingMigrationTest, TestIconMappingMigration);
149  // Implemented for URLDatabase.
150  virtual sql::Connection& GetDB();
151
152  // Migration -----------------------------------------------------------------
153
154  // Makes sure the version is up-to-date, updating if necessary. If the
155  // database is too old to migrate, the user will be notified. In this case, or
156  // for other errors, false will be returned. True means it is up-to-date and
157  // ready for use.
158  //
159  // This assumes it is called from the init function inside a transaction. It
160  // may commit the transaction and start a new one if migration requires it.
161  sql::InitStatus EnsureCurrentVersion(const FilePath& tmp_bookmarks_path);
162
163#if !defined(OS_WIN)
164  // Converts the time epoch in the database from being 1970-based to being
165  // 1601-based which corresponds to the change in Time.internal_value_.
166  void MigrateTimeEpoch();
167#endif
168
169  // ---------------------------------------------------------------------------
170
171  sql::Connection db_;
172  sql::MetaTable meta_table_;
173
174  base::Time cached_early_expiration_threshold_;
175
176  // See the getters above.
177  bool needs_version_17_migration_;
178
179  DISALLOW_COPY_AND_ASSIGN(HistoryDatabase);
180};
181
182}  // history
183
184#endif  // CHROME_BROWSER_HISTORY_HISTORY_DATABASE_H_
185