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 27 class BookmarkService; 28 struct DownloadCreateInfo; 29 class TestingProfile; 30 struct ThumbnailScore; 31 32 namespace history { 33 34 class CommitLaterTask; 35 class 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. 48 class 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