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#ifndef CHROME_BROWSER_HISTORY_HISTORY_BACKEND_H_
6#define CHROME_BROWSER_HISTORY_HISTORY_BACKEND_H_
7#pragma once
8
9#include <string>
10#include <utility>
11
12#include "app/sql/init_status.h"
13#include "base/file_path.h"
14#include "base/gtest_prod_util.h"
15#include "base/memory/scoped_ptr.h"
16#include "chrome/browser/history/archived_database.h"
17#include "chrome/browser/history/expire_history_backend.h"
18#include "chrome/browser/history/history_database.h"
19#include "chrome/browser/history/history_marshaling.h"
20#include "chrome/browser/history/history_types.h"
21#include "chrome/browser/history/text_database_manager.h"
22#include "chrome/browser/history/thumbnail_database.h"
23#include "chrome/browser/history/visit_tracker.h"
24#include "chrome/browser/search_engines/template_url_id.h"
25#include "content/common/mru_cache.h"
26
27class BookmarkService;
28struct DownloadCreateInfo;
29class TestingProfile;
30struct ThumbnailScore;
31
32namespace history {
33
34class CommitLaterTask;
35class HistoryPublisher;
36
37// *See the .cc file for more information on the design.*
38//
39// Internal history implementation which does most of the work of the history
40// system. This runs on a background thread (to not block the browser when we
41// do expensive operations) and is NOT threadsafe, so it must only be called
42// from message handlers on the background thread. Invoking on another thread
43// requires threadsafe refcounting.
44//
45// Most functions here are just the implementations of the corresponding
46// functions in the history service. These functions are not documented
47// here, see the history service for behavior.
48class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
49                       public BroadcastNotificationDelegate {
50 public:
51  // Interface implemented by the owner of the HistoryBackend object. Normally,
52  // the history service implements this to send stuff back to the main thread.
53  // The unit tests can provide a different implementation if they don't have
54  // a history service object.
55  class Delegate {
56   public:
57    virtual ~Delegate() {}
58
59    // Called when the database cannot be read correctly for some reason.
60    virtual void NotifyProfileError(sql::InitStatus init_status) = 0;
61
62    // Sets the in-memory history backend. The in-memory backend is created by
63    // the main backend. For non-unit tests, this happens on the background
64    // thread. It is to be used on the main thread, so this would transfer
65    // it to the history service. Unit tests can override this behavior.
66    //
67    // This function is NOT guaranteed to be called. If there is an error,
68    // there may be no in-memory database.
69    //
70    // Ownership of the backend pointer is transferred to this function.
71    virtual void SetInMemoryBackend(InMemoryHistoryBackend* backend) = 0;
72
73    // Broadcasts the specified notification to the notification service.
74    // This is implemented here because notifications must only be sent from
75    // the main thread.
76    //
77    // Ownership of the HistoryDetails is transferred to this function.
78    virtual void BroadcastNotifications(NotificationType type,
79                                        HistoryDetails* details) = 0;
80
81    // Invoked when the backend has finished loading the db.
82    virtual void DBLoaded() = 0;
83
84    // Tell TopSites to start reading thumbnails from the ThumbnailsDB.
85    virtual void StartTopSitesMigration() = 0;
86  };
87
88  // Init must be called to complete object creation. This object can be
89  // constructed on any thread, but all other functions including Init() must
90  // be called on the history thread.
91  //
92  // |history_dir| is the directory where the history files will be placed.
93  // See the definition of BroadcastNotificationsCallback above. This function
94  // takes ownership of the callback pointer.
95  //
96  // |bookmark_service| is used to determine bookmarked URLs when deleting and
97  // may be NULL.
98  //
99  // This constructor is fast and does no I/O, so can be called at any time.
100  HistoryBackend(const FilePath& history_dir,
101                 Delegate* delegate,
102                 BookmarkService* bookmark_service);
103
104  // Must be called after creation but before any objects are created. If this
105  // fails, all other functions will fail as well. (Since this runs on another
106  // thread, we don't bother returning failure.)
107  //
108  // |languages| gives a list of language encodings with which the history
109  // URLs and omnibox searches are interpreted.
110  // |force_fail| can be set during unittests to unconditionally fail to init.
111  void Init(const std::string& languages, bool force_fail);
112
113  // Notification that the history system is shutting down. This will break
114  // the refs owned by the delegate and any pending transaction so it will
115  // actually be deleted.
116  void Closing();
117
118  // See NotifyRenderProcessHostDestruction.
119  void NotifyRenderProcessHostDestruction(const void* host);
120
121  // Navigation ----------------------------------------------------------------
122
123  void AddPage(scoped_refptr<HistoryAddPageArgs> request);
124  virtual void SetPageTitle(const GURL& url, const string16& title);
125  void AddPageNoVisitForBookmark(const GURL& url);
126
127  // Indexing ------------------------------------------------------------------
128
129  void SetPageContents(const GURL& url, const string16& contents);
130
131  // Querying ------------------------------------------------------------------
132
133  // ScheduleAutocomplete() never frees |provider| (which is globally live).
134  // It passes |params| on to the autocomplete system which will eventually
135  // free it.
136  void ScheduleAutocomplete(HistoryURLProvider* provider,
137                            HistoryURLProviderParams* params);
138
139  void IterateURLs(HistoryService::URLEnumerator* enumerator);
140  void QueryURL(scoped_refptr<QueryURLRequest> request,
141                const GURL& url,
142                bool want_visits);
143  void QueryHistory(scoped_refptr<QueryHistoryRequest> request,
144                    const string16& text_query,
145                    const QueryOptions& options);
146  void QueryRedirectsFrom(scoped_refptr<QueryRedirectsRequest> request,
147                          const GURL& url);
148  void QueryRedirectsTo(scoped_refptr<QueryRedirectsRequest> request,
149                        const GURL& url);
150
151  void GetVisitCountToHost(scoped_refptr<GetVisitCountToHostRequest> request,
152                           const GURL& url);
153
154  // TODO(Nik): remove. Use QueryMostVisitedURLs instead.
155  void QueryTopURLsAndRedirects(
156      scoped_refptr<QueryTopURLsAndRedirectsRequest> request,
157      int result_count);
158
159  // Request the |result_count| most visited URLs and the chain of
160  // redirects leading to each of these URLs. |days_back| is the
161  // number of days of history to use. Used by TopSites.
162  void QueryMostVisitedURLs(
163      scoped_refptr<QueryMostVisitedURLsRequest> request,
164      int result_count,
165      int days_back);
166
167  // QueryMostVisitedURLs without the request.
168  void QueryMostVisitedURLsImpl(int result_count,
169                                int days_back,
170                                MostVisitedURLList* result);
171
172  // Computes the most recent URL(s) that the given canonical URL has
173  // redirected to and returns true on success. There may be more than one
174  // redirect in a row, so this function will fill the given array with the
175  // entire chain. If there are no redirects for the most recent visit of the
176  // URL, or the URL is not in history, returns false.
177  //
178  // Backend for QueryRedirectsFrom.
179  bool GetMostRecentRedirectsFrom(const GURL& url,
180                                  history::RedirectList* redirects);
181
182  // Similar to above function except computes a chain of redirects to the
183  // given URL. Stores the most recent list of redirects ending at |url| in the
184  // given RedirectList. For example, if we have the redirect list A -> B -> C,
185  // then calling this function with url=C would fill redirects with {B, A}.
186  bool GetMostRecentRedirectsTo(const GURL& url,
187                                      history::RedirectList* redirects);
188
189  // Thumbnails ----------------------------------------------------------------
190
191  void SetPageThumbnail(const GURL& url,
192                        const SkBitmap& thumbnail,
193                        const ThumbnailScore& score);
194
195  // Retrieves a thumbnail, passing it across thread boundaries
196  // via. the included callback.
197  void GetPageThumbnail(scoped_refptr<GetPageThumbnailRequest> request,
198                        const GURL& page_url);
199
200  // Backend implementation of GetPageThumbnail. Unlike
201  // GetPageThumbnail(), this method has way to transport data across
202  // thread boundaries.
203  //
204  // Exposed for testing reasons.
205  void GetPageThumbnailDirectly(
206      const GURL& page_url,
207      scoped_refptr<RefCountedBytes>* data);
208
209  void MigrateThumbnailsDatabase();
210
211  // Favicon -------------------------------------------------------------------
212
213  void GetFavicon(scoped_refptr<GetFaviconRequest> request,
214                  const GURL& icon_url,
215                  int icon_types);
216
217  void GetFaviconForURL(scoped_refptr<GetFaviconRequest> request,
218                        const GURL& page_url,
219                        int icon_types);
220
221  void SetFavicon(const GURL& page_url,
222                  const GURL& icon_url,
223                  scoped_refptr<RefCountedMemory> data,
224                  IconType icon_type);
225
226  void UpdateFaviconMappingAndFetch(scoped_refptr<GetFaviconRequest> request,
227                                    const GURL& page_url,
228                                    const GURL& icon_url,
229                                    IconType icon_type);
230
231  void SetFaviconOutOfDateForPage(const GURL& page_url);
232
233  void SetImportedFavicons(
234      const std::vector<ImportedFaviconUsage>& favicon_usage);
235
236  // Downloads -----------------------------------------------------------------
237
238  void QueryDownloads(scoped_refptr<DownloadQueryRequest> request);
239  void CleanUpInProgressEntries();
240  void UpdateDownload(int64 received_bytes, int32 state, int64 db_handle);
241  void UpdateDownloadPath(const FilePath& path, int64 db_handle);
242  void CreateDownload(scoped_refptr<DownloadCreateRequest> request,
243                      const DownloadCreateInfo& info);
244  void RemoveDownload(int64 db_handle);
245  void RemoveDownloadsBetween(const base::Time remove_begin,
246                              const base::Time remove_end);
247  void RemoveDownloads(const base::Time remove_end);
248
249  // Segment usage -------------------------------------------------------------
250
251  void QuerySegmentUsage(scoped_refptr<QuerySegmentUsageRequest> request,
252                         const base::Time from_time,
253                         int max_result_count);
254  void DeleteOldSegmentData();
255  void SetSegmentPresentationIndex(SegmentID segment_id, int index);
256
257  // Keyword search terms ------------------------------------------------------
258
259  void SetKeywordSearchTermsForURL(const GURL& url,
260                                   TemplateURLID keyword_id,
261                                   const string16& term);
262
263  void DeleteAllSearchTermsForKeyword(TemplateURLID keyword_id);
264
265  void GetMostRecentKeywordSearchTerms(
266      scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request,
267      TemplateURLID keyword_id,
268      const string16& prefix,
269      int max_count);
270
271  // Generic operations --------------------------------------------------------
272
273  void ProcessDBTask(scoped_refptr<HistoryDBTaskRequest> request);
274
275  virtual bool GetAllTypedURLs(std::vector<history::URLRow>* urls);
276
277  virtual bool GetVisitsForURL(URLID id, VisitVector* visits);
278
279  virtual bool UpdateURL(URLID id, const history::URLRow& url);
280
281  // While adding visits in batch, the source needs to be provided.
282  virtual bool AddVisits(const GURL& url,
283                         const std::vector<base::Time>& visits,
284                         VisitSource visit_source);
285
286  virtual bool RemoveVisits(const VisitVector& visits);
287
288  virtual bool GetURL(const GURL& url, history::URLRow* url_row);
289
290  // Deleting ------------------------------------------------------------------
291
292  virtual void DeleteURLs(const std::vector<GURL>& urls);
293
294  virtual void DeleteURL(const GURL& url);
295
296  // Calls ExpireHistoryBackend::ExpireHistoryBetween and commits the change.
297  void ExpireHistoryBetween(scoped_refptr<ExpireHistoryRequest> request,
298                            const std::set<GURL>& restrict_urls,
299                            base::Time begin_time,
300                            base::Time end_time);
301
302  // Bookmarks -----------------------------------------------------------------
303
304  // Notification that a URL is no longer bookmarked. If there are no visits
305  // for the specified url, it is deleted.
306  void URLsNoLongerBookmarked(const std::set<GURL>& urls);
307
308  // Testing -------------------------------------------------------------------
309
310  // Sets the task to run and the message loop to run it on when this object
311  // is destroyed. See HistoryService::SetOnBackendDestroyTask for a more
312  // complete description.
313  void SetOnBackendDestroyTask(MessageLoop* message_loop, Task* task);
314
315  // Adds the given rows to the database if it doesn't exist. A visit will be
316  // added for each given URL at the last visit time in the URLRow.
317  // Each visit will have the visit_source type set.
318  void AddPagesWithDetails(const std::vector<URLRow>& info,
319                           VisitSource visit_source);
320
321#if defined(UNIT_TEST)
322  HistoryDatabase* db() const { return db_.get(); }
323
324  ExpireHistoryBackend* expire_backend() { return &expirer_; }
325#endif
326
327 protected:
328  virtual ~HistoryBackend();
329
330 private:
331  friend class base::RefCountedThreadSafe<HistoryBackend>;
332  friend class CommitLaterTask;  // The commit task needs to call Commit().
333  friend class HistoryBackendTest;
334  friend class HistoryTest;  // So the unit tests can poke our innards.
335  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, DeleteAll);
336  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, ImportedFaviconsTest);
337  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, URLsNoLongerBookmarked);
338  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, StripUsernamePasswordTest);
339  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, DeleteThumbnailsDatabaseTest);
340  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddPageVisitSource);
341  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddPageArgsSource);
342  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddVisitsSource);
343  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, RemoveVisitsSource);
344  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MigrationVisitSource);
345  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MigrationIconMapping);
346  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetFaviconMapping);
347  FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddOrUpdateIconMapping);
348
349  friend class ::TestingProfile;
350
351  // Computes the name of the specified database on disk.
352  FilePath GetThumbnailFileName() const;
353
354  // Returns the name of the Favicons database. This is the new name
355  // of the Thumbnails database.
356  // See ThumbnailDatabase::RenameAndDropThumbnails.
357  FilePath GetFaviconsFileName() const;
358  FilePath GetArchivedFileName() const;
359
360  class URLQuerier;
361  friend class URLQuerier;
362
363  // Does the work of Init.
364  void InitImpl(const std::string& languages);
365
366  // Adds a single visit to the database, updating the URL information such
367  // as visit and typed count. The visit ID of the added visit and the URL ID
368  // of the associated URL (whether added or not) is returned. Both values will
369  // be 0 on failure.
370  //
371  // This does not schedule database commits, it is intended to be used as a
372  // subroutine for AddPage only. It also assumes the database is valid.
373  std::pair<URLID, VisitID> AddPageVisit(const GURL& url,
374                                         base::Time time,
375                                         VisitID referring_visit,
376                                         PageTransition::Type transition,
377                                         VisitSource visit_source);
378
379  // Returns a redirect chain in |redirects| for the VisitID
380  // |cur_visit|. |cur_visit| is assumed to be valid. Assumes that
381  // this HistoryBackend object has been Init()ed successfully.
382  void GetRedirectsFromSpecificVisit(
383      VisitID cur_visit, history::RedirectList* redirects);
384
385  // Similar to the above function except returns a redirect list ending
386  // at |cur_visit|.
387  void GetRedirectsToSpecificVisit(
388      VisitID cur_visit, history::RedirectList* redirects);
389
390  // Thumbnail Helpers ---------------------------------------------------------
391
392  // When a simple GetMostRecentRedirectsFrom() fails, this method is
393  // called which searches the last N visit sessions instead of just
394  // the current one. Returns true and puts thumbnail data in |data|
395  // if a proper thumbnail was found. Returns false otherwise. Assumes
396  // that this HistoryBackend object has been Init()ed successfully.
397  bool GetThumbnailFromOlderRedirect(
398      const GURL& page_url, std::vector<unsigned char>* data);
399
400  // Querying ------------------------------------------------------------------
401
402  // Backends for QueryHistory. *Basic() handles queries that are not FTS (full
403  // text search) queries and can just be given directly to the history DB).
404  // The FTS version queries the text_database, then merges with the history DB.
405  // Both functions assume QueryHistory already checked the DB for validity.
406  void QueryHistoryBasic(URLDatabase* url_db, VisitDatabase* visit_db,
407                         const QueryOptions& options, QueryResults* result);
408  void QueryHistoryFTS(const string16& text_query,
409                       const QueryOptions& options,
410                       QueryResults* result);
411
412  // Committing ----------------------------------------------------------------
413
414  // We always keep a transaction open on the history database so that multiple
415  // transactions can be batched. Periodically, these are flushed (use
416  // ScheduleCommit). This function does the commit to write any new changes to
417  // disk and opens a new transaction. This will be called automatically by
418  // ScheduleCommit, or it can be called explicitly if a caller really wants
419  // to write something to disk.
420  void Commit();
421
422  // Schedules a commit to happen in the future. We do this so that many
423  // operations over a period of time will be batched together. If there is
424  // already a commit scheduled for the future, this will do nothing.
425  void ScheduleCommit();
426
427  // Cancels the scheduled commit, if any. If there is no scheduled commit,
428  // does nothing.
429  void CancelScheduledCommit();
430
431  // Segments ------------------------------------------------------------------
432
433  // Walks back a segment chain to find the last visit with a non null segment
434  // id and returns it. If there is none found, returns 0.
435  SegmentID GetLastSegmentID(VisitID from_visit);
436
437  // Update the segment information. This is called internally when a page is
438  // added. Return the segment id of the segment that has been updated.
439  SegmentID UpdateSegments(const GURL& url,
440                           VisitID from_visit,
441                           VisitID visit_id,
442                           PageTransition::Type transition_type,
443                           const base::Time ts);
444
445  // Favicons ------------------------------------------------------------------
446
447  // Used by both UpdateFaviconMappingAndFetch and GetFavicon.
448  // If page_url is non-null and SetFavicon has previously been invoked for
449  // icon_url the favicon url for page_url (and all redirects) is set to
450  // icon_url.
451  // Only a single type can be given in icon_type when page_url is specified.
452  void UpdateFaviconMappingAndFetchImpl(
453      const GURL* page_url,
454      const GURL& icon_url,
455      scoped_refptr<GetFaviconRequest> request,
456      int icon_type);
457
458  // Sets the favicon url id for page_url to id. This will also broadcast
459  // notifications as necessary.
460  void SetFaviconMapping(const GURL& page_url,
461                         FaviconID id,
462                         IconType icon_type);
463
464  // Updates the FaviconID associated with the url of a page. If there is an
465  // existing mapping between |page_url| and |id| this does nothing and returns
466  // false. If the mapping needs to be added or updated, true is returned. If
467  // there is an existing mapping but it does not map to |id|, then the |id| of
468  // the replaced FaviconID is set in |replaced_icon_id|.
469  bool AddOrUpdateIconMapping(const GURL& page_url,
470                              FaviconID id,
471                              IconType icon_type,
472                              FaviconID* replaced_icon_id);
473
474  // Generic stuff -------------------------------------------------------------
475
476  // Processes the next scheduled HistoryDBTask, scheduling this method
477  // to be invoked again if there are more tasks that need to run.
478  void ProcessDBTaskImpl();
479
480  // Release all tasks in history_db_tasks_ and clears it.
481  void ReleaseDBTasks();
482
483  // Schedules a broadcast of the given notification on the main thread. The
484  // details argument will have ownership taken by this function (it will be
485  // sent to the main thread and deleted there).
486  virtual void BroadcastNotifications(NotificationType type,
487                                      HistoryDetails* details_deleted);
488
489  // Deleting all history ------------------------------------------------------
490
491  // Deletes all history. This is a special case of deleting that is separated
492  // from our normal dependency-following method for performance reasons. The
493  // logic lives here instead of ExpireHistoryBackend since it will cause
494  // re-initialization of some databases such as Thumbnails or Archived that
495  // could fail. When these databases are not valid, our pointers must be NULL,
496  // so we need to handle this type of operation to keep the pointers in sync.
497  void DeleteAllHistory();
498
499  // Given a vector of all URLs that we will keep, removes all thumbnails
500  // referenced by any URL, and also all favicons that aren't used by those
501  // URLs. The favicon IDs will change, so this will update the url rows in the
502  // vector to reference the new IDs.
503  bool ClearAllThumbnailHistory(std::vector<URLRow>* kept_urls);
504
505  // Deletes all information in the history database, except for the supplied
506  // set of URLs in the URL table (these should correspond to the bookmarked
507  // URLs).
508  //
509  // The IDs of the URLs may change.
510  bool ClearAllMainHistory(const std::vector<URLRow>& kept_urls);
511
512  // Returns the BookmarkService, blocking until it is loaded. This may return
513  // NULL during testing.
514  BookmarkService* GetBookmarkService();
515
516  // Data ----------------------------------------------------------------------
517
518  // Delegate. See the class definition above for more information. This will
519  // be NULL before Init is called and after Cleanup, but is guaranteed
520  // non-NULL in between.
521  scoped_ptr<Delegate> delegate_;
522
523  // Directory where database files will be stored.
524  FilePath history_dir_;
525
526  // The history/thumbnail databases. Either MAY BE NULL if the database could
527  // not be opened, all users must first check for NULL and return immediately
528  // if it is. The thumbnail DB may be NULL when the history one isn't, but not
529  // vice-versa.
530  scoped_ptr<HistoryDatabase> db_;
531  scoped_ptr<ThumbnailDatabase> thumbnail_db_;
532
533  // Stores old history in a larger, slower database.
534  scoped_ptr<ArchivedDatabase> archived_db_;
535
536  // Full text database manager, possibly NULL if the database could not be
537  // created.
538  scoped_ptr<TextDatabaseManager> text_database_;
539
540  // Manages expiration between the various databases.
541  ExpireHistoryBackend expirer_;
542
543  // A commit has been scheduled to occur sometime in the future. We can check
544  // non-null-ness to see if there is a commit scheduled in the future, and we
545  // can use the pointer to cancel the scheduled commit. There can be only one
546  // scheduled commit at a time (see ScheduleCommit).
547  scoped_refptr<CommitLaterTask> scheduled_commit_;
548
549  // Maps recent redirect destination pages to the chain of redirects that
550  // brought us to there. Pages that did not have redirects or were not the
551  // final redirect in a chain will not be in this list, as well as pages that
552  // redirected "too long" ago (as determined by ExpireOldRedirects above).
553  // It is used to set titles & favicons for redirects to that of the
554  // destination.
555  //
556  // As with AddPage, the last item in the redirect chain will be the
557  // destination of the redirect (i.e., the key into recent_redirects_);
558  typedef MRUCache<GURL, history::RedirectList> RedirectCache;
559  RedirectCache recent_redirects_;
560
561  // Timestamp of the last page addition request. We use this to detect when
562  // multiple additions are requested at the same time (within the resolution
563  // of the timer), so we can try to ensure they're unique when they're added
564  // to the database by using the last_recorded_time_ (q.v.). We still can't
565  // enforce or guarantee uniqueness, since the user might set his clock back.
566  base::Time last_requested_time_;
567
568  // Timestamp of the last page addition, as it was recorded in the database.
569  // If two or more requests come in at the same time, we increment that time
570  // by 1 us between them so it's more likely to be unique in the database.
571  // This keeps track of that higher-resolution timestamp.
572  base::Time last_recorded_time_;
573
574  // Timestamp of the first entry in our database.
575  base::Time first_recorded_time_;
576
577  // When non-NULL, this is the task that should be invoked on
578  MessageLoop* backend_destroy_message_loop_;
579  Task* backend_destroy_task_;
580
581  // Tracks page transition types.
582  VisitTracker tracker_;
583
584  // A boolean variable to track whether we have already purged obsolete segment
585  // data.
586  bool segment_queried_;
587
588  // HistoryDBTasks to run. Be sure to AddRef when adding, and Release when
589  // done.
590  std::list<HistoryDBTaskRequest*> db_task_requests_;
591
592  // Used to determine if a URL is bookmarked. This is owned by the Profile and
593  // may be NULL (during testing).
594  //
595  // Use GetBookmarkService to access this, which makes sure the service is
596  // loaded.
597  BookmarkService* bookmark_service_;
598
599  // Publishes the history to all indexers which are registered to receive
600  // history data from us. Can be NULL if there are no listeners.
601  scoped_ptr<HistoryPublisher> history_publisher_;
602
603  DISALLOW_COPY_AND_ASSIGN(HistoryBackend);
604};
605
606}  // namespace history
607
608#endif  // CHROME_BROWSER_HISTORY_HISTORY_BACKEND_H_
609