summaryrefslogtreecommitdiffstats
path: root/chrome/browser/history/history_backend.h
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/history/history_backend.h')
-rw-r--r--chrome/browser/history/history_backend.h560
1 files changed, 560 insertions, 0 deletions
diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h
new file mode 100644
index 0000000..cbda2e9
--- /dev/null
+++ b/chrome/browser/history/history_backend.h
@@ -0,0 +1,560 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_HISTORY_HISTORY_BACKEND_H_
+#define CHROME_BROWSER_HISTORY_HISTORY_BACKEND_H_
+
+#include <utility>
+
+#include "base/file_path.h"
+#include "base/gtest_prod_util.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/history/archived_database.h"
+#include "chrome/browser/history/download_types.h"
+#include "chrome/browser/history/expire_history_backend.h"
+#include "chrome/browser/history/history_database.h"
+#include "chrome/browser/history/history_marshaling.h"
+#include "chrome/browser/history/history_types.h"
+#include "chrome/browser/history/text_database_manager.h"
+#include "chrome/browser/history/thumbnail_database.h"
+#include "chrome/browser/history/visit_tracker.h"
+#include "chrome/common/mru_cache.h"
+
+class BookmarkService;
+class TestingProfile;
+struct ThumbnailScore;
+
+namespace history {
+
+class CommitLaterTask;
+class HistoryPublisher;
+
+// *See the .cc file for more information on the design.*
+//
+// Internal history implementation which does most of the work of the history
+// system. This runs on a background thread (to not block the browser when we
+// do expensive operations) and is NOT threadsafe, so it must only be called
+// from message handlers on the background thread. Invoking on another thread
+// requires threadsafe refcounting.
+//
+// Most functions here are just the implementations of the corresponding
+// functions in the history service. These functions are not documented
+// here, see the history service for behavior.
+class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
+ public BroadcastNotificationDelegate {
+ public:
+ // Interface implemented by the owner of the HistoryBackend object. Normally,
+ // the history service implements this to send stuff back to the main thread.
+ // The unit tests can provide a different implementation if they don't have
+ // a history service object.
+ class Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // Called when the database cannot be read correctly for some reason.
+ virtual void NotifyProfileError(int message_id) = 0;
+
+ // Sets the in-memory history backend. The in-memory backend is created by
+ // the main backend. For non-unit tests, this happens on the background
+ // thread. It is to be used on the main thread, so this would transfer
+ // it to the history service. Unit tests can override this behavior.
+ //
+ // This function is NOT guaranteed to be called. If there is an error,
+ // there may be no in-memory database.
+ //
+ // Ownership of the backend pointer is transferred to this function.
+ virtual void SetInMemoryBackend(InMemoryHistoryBackend* backend) = 0;
+
+ // Broadcasts the specified notification to the notification service.
+ // This is implemented here because notifications must only be sent from
+ // the main thread.
+ //
+ // Ownership of the HistoryDetails is transferred to this function.
+ virtual void BroadcastNotifications(NotificationType type,
+ HistoryDetails* details) = 0;
+
+ // Invoked when the backend has finished loading the db.
+ virtual void DBLoaded() = 0;
+
+ // Tell TopSites to start reading thumbnails from the ThumbnailsDB.
+ virtual void StartTopSitesMigration() = 0;
+ };
+
+ // Init must be called to complete object creation. This object can be
+ // constructed on any thread, but all other functions including Init() must
+ // be called on the history thread.
+ //
+ // |history_dir| is the directory where the history files will be placed.
+ // See the definition of BroadcastNotificationsCallback above. This function
+ // takes ownership of the callback pointer.
+ //
+ // |bookmark_service| is used to determine bookmarked URLs when deleting and
+ // may be NULL.
+ //
+ // This constructor is fast and does no I/O, so can be called at any time.
+ HistoryBackend(const FilePath& history_dir,
+ Delegate* delegate,
+ BookmarkService* bookmark_service);
+
+ // Must be called after creation but before any objects are created. If this
+ // fails, all other functions will fail as well. (Since this runs on another
+ // thread, we don't bother returning failure.)
+ //
+ // |force_fail| can be set during unittests to unconditionally fail to init.
+ void Init(bool force_fail);
+
+ // Notification that the history system is shutting down. This will break
+ // the refs owned by the delegate and any pending transaction so it will
+ // actually be deleted.
+ void Closing();
+
+ // See NotifyRenderProcessHostDestruction.
+ void NotifyRenderProcessHostDestruction(const void* host);
+
+ // Navigation ----------------------------------------------------------------
+
+ void AddPage(scoped_refptr<HistoryAddPageArgs> request);
+ virtual void SetPageTitle(const GURL& url, const string16& title);
+
+ // Indexing ------------------------------------------------------------------
+
+ void SetPageContents(const GURL& url, const string16& contents);
+
+ // Querying ------------------------------------------------------------------
+
+ // ScheduleAutocomplete() never frees |provider| (which is globally live).
+ // It passes |params| on to the autocomplete system which will eventually
+ // free it.
+ void ScheduleAutocomplete(HistoryURLProvider* provider,
+ HistoryURLProviderParams* params);
+
+ void IterateURLs(HistoryService::URLEnumerator* enumerator);
+ void QueryURL(scoped_refptr<QueryURLRequest> request,
+ const GURL& url,
+ bool want_visits);
+ void QueryHistory(scoped_refptr<QueryHistoryRequest> request,
+ const string16& text_query,
+ const QueryOptions& options);
+ void QueryRedirectsFrom(scoped_refptr<QueryRedirectsRequest> request,
+ const GURL& url);
+ void QueryRedirectsTo(scoped_refptr<QueryRedirectsRequest> request,
+ const GURL& url);
+
+ void GetVisitCountToHost(scoped_refptr<GetVisitCountToHostRequest> request,
+ const GURL& url);
+
+ // TODO(Nik): remove. Use QueryMostVisitedURLs instead.
+ void QueryTopURLsAndRedirects(
+ scoped_refptr<QueryTopURLsAndRedirectsRequest> request,
+ int result_count);
+
+ // Request the |result_count| most visited URLs and the chain of
+ // redirects leading to each of these URLs. |days_back| is the
+ // number of days of history to use. Used by TopSites.
+ void QueryMostVisitedURLs(
+ scoped_refptr<QueryMostVisitedURLsRequest> request,
+ int result_count,
+ int days_back);
+
+ // Computes the most recent URL(s) that the given canonical URL has
+ // redirected to and returns true on success. There may be more than one
+ // redirect in a row, so this function will fill the given array with the
+ // entire chain. If there are no redirects for the most recent visit of the
+ // URL, or the URL is not in history, returns false.
+ //
+ // Backend for QueryRedirectsFrom.
+ bool GetMostRecentRedirectsFrom(const GURL& url,
+ history::RedirectList* redirects);
+
+ // Similar to above function except computes a chain of redirects to the
+ // given URL. Stores the most recent list of redirects ending at |url| in the
+ // given RedirectList. For example, if we have the redirect list A -> B -> C,
+ // then calling this function with url=C would fill redirects with {B, A}.
+ bool GetMostRecentRedirectsTo(const GURL& url,
+ history::RedirectList* redirects);
+
+ // Thumbnails ----------------------------------------------------------------
+
+ void SetPageThumbnail(const GURL& url,
+ const SkBitmap& thumbnail,
+ const ThumbnailScore& score);
+
+ // Retrieves a thumbnail, passing it across thread boundaries
+ // via. the included callback.
+ void GetPageThumbnail(scoped_refptr<GetPageThumbnailRequest> request,
+ const GURL& page_url);
+
+ // Backend implementation of GetPageThumbnail. Unlike
+ // GetPageThumbnail(), this method has way to transport data across
+ // thread boundaries.
+ //
+ // Exposed for testing reasons.
+ void GetPageThumbnailDirectly(
+ const GURL& page_url,
+ scoped_refptr<RefCountedBytes>* data);
+
+ void MigrateThumbnailsDatabase();
+
+ // Favicon -------------------------------------------------------------------
+
+ void GetFavIcon(scoped_refptr<GetFavIconRequest> request,
+ const GURL& icon_url);
+ void GetFavIconForURL(scoped_refptr<GetFavIconRequest> request,
+ const GURL& page_url);
+ void SetFavIcon(const GURL& page_url,
+ const GURL& icon_url,
+ scoped_refptr<RefCountedMemory> data);
+ void UpdateFavIconMappingAndFetch(scoped_refptr<GetFavIconRequest> request,
+ const GURL& page_url,
+ const GURL& icon_url);
+ void SetFavIconOutOfDateForPage(const GURL& page_url);
+ void SetImportedFavicons(
+ const std::vector<ImportedFavIconUsage>& favicon_usage);
+
+ // Downloads -----------------------------------------------------------------
+
+ void QueryDownloads(scoped_refptr<DownloadQueryRequest> request);
+ void CleanUpInProgressEntries();
+ void UpdateDownload(int64 received_bytes, int32 state, int64 db_handle);
+ void UpdateDownloadPath(const FilePath& path, int64 db_handle);
+ void CreateDownload(scoped_refptr<DownloadCreateRequest> request,
+ const DownloadCreateInfo& info);
+ void RemoveDownload(int64 db_handle);
+ void RemoveDownloadsBetween(const base::Time remove_begin,
+ const base::Time remove_end);
+ void RemoveDownloads(const base::Time remove_end);
+ void SearchDownloads(scoped_refptr<DownloadSearchRequest>,
+ const string16& search_text);
+
+ // Segment usage -------------------------------------------------------------
+
+ void QuerySegmentUsage(scoped_refptr<QuerySegmentUsageRequest> request,
+ const base::Time from_time,
+ int max_result_count);
+ void DeleteOldSegmentData();
+ void SetSegmentPresentationIndex(SegmentID segment_id, int index);
+
+ // Keyword search terms ------------------------------------------------------
+
+ void SetKeywordSearchTermsForURL(const GURL& url,
+ TemplateURL::IDType keyword_id,
+ const string16& term);
+
+ void DeleteAllSearchTermsForKeyword(TemplateURL::IDType keyword_id);
+
+ void GetMostRecentKeywordSearchTerms(
+ scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request,
+ TemplateURL::IDType keyword_id,
+ const string16& prefix,
+ int max_count);
+
+ // Generic operations --------------------------------------------------------
+
+ void ProcessDBTask(scoped_refptr<HistoryDBTaskRequest> request);
+
+ virtual bool GetAllTypedURLs(std::vector<history::URLRow>* urls);
+
+ virtual bool GetVisitsForURL(URLID id, VisitVector* visits);
+
+ virtual bool UpdateURL(URLID id, const history::URLRow& url);
+
+ virtual bool AddVisits(const GURL& url,
+ const std::vector<base::Time>& visits);
+
+ virtual bool RemoveVisits(const VisitVector& visits);
+
+ virtual bool GetURL(const GURL& url, history::URLRow* url_row);
+
+ // Deleting ------------------------------------------------------------------
+
+ virtual void DeleteURLs(const std::vector<GURL>& urls);
+
+ virtual void DeleteURL(const GURL& url);
+
+ // Calls ExpireHistoryBackend::ExpireHistoryBetween and commits the change.
+ void ExpireHistoryBetween(scoped_refptr<ExpireHistoryRequest> request,
+ const std::set<GURL>& restrict_urls,
+ base::Time begin_time,
+ base::Time end_time);
+
+ // Bookmarks -----------------------------------------------------------------
+
+ // Notification that a URL is no longer bookmarked. If there are no visits
+ // for the specified url, it is deleted.
+ void URLsNoLongerBookmarked(const std::set<GURL>& urls);
+
+ // Testing -------------------------------------------------------------------
+
+ // Sets the task to run and the message loop to run it on when this object
+ // is destroyed. See HistoryService::SetOnBackendDestroyTask for a more
+ // complete description.
+ void SetOnBackendDestroyTask(MessageLoop* message_loop, Task* task);
+
+ // Adds the given rows to the database if it doesn't exist. A visit will be
+ // added for each given URL at the last visit time in the URLRow.
+ void AddPagesWithDetails(const std::vector<URLRow>& info);
+
+#if defined(UNIT_TEST)
+ HistoryDatabase* db() const { return db_.get(); }
+
+ ExpireHistoryBackend* expire_backend() { return &expirer_; }
+#endif
+
+ protected:
+ virtual ~HistoryBackend();
+
+ private:
+ friend class base::RefCountedThreadSafe<HistoryBackend>;
+ friend class CommitLaterTask; // The commit task needs to call Commit().
+ friend class HistoryTest; // So the unit tests can poke our innards.
+ FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, DeleteAll);
+ FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, ImportedFaviconsTest);
+ FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, URLsNoLongerBookmarked);
+ FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, StripUsernamePasswordTest);
+ FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, DeleteThumbnailsDatabaseTest);
+ friend class ::TestingProfile;
+
+ // Computes the name of the specified database on disk.
+ FilePath GetThumbnailFileName() const;
+
+ // Returns the name of the Favicons database. This is the new name
+ // of the Thumbnails database.
+ // See ThumbnailDatabase::RenameAndDropThumbnails.
+ FilePath GetFaviconsFileName() const;
+ FilePath GetArchivedFileName() const;
+
+ class URLQuerier;
+ friend class URLQuerier;
+
+ // Does the work of Init.
+ void InitImpl();
+
+ // Adds a single visit to the database, updating the URL information such
+ // as visit and typed count. The visit ID of the added visit and the URL ID
+ // of the associated URL (whether added or not) is returned. Both values will
+ // be 0 on failure.
+ //
+ // This does not schedule database commits, it is intended to be used as a
+ // subroutine for AddPage only. It also assumes the database is valid.
+ std::pair<URLID, VisitID> AddPageVisit(const GURL& url,
+ base::Time time,
+ VisitID referring_visit,
+ PageTransition::Type transition);
+
+ // Returns a redirect chain in |redirects| for the VisitID
+ // |cur_visit|. |cur_visit| is assumed to be valid. Assumes that
+ // this HistoryBackend object has been Init()ed successfully.
+ void GetRedirectsFromSpecificVisit(
+ VisitID cur_visit, history::RedirectList* redirects);
+
+ // Similar to the above function except returns a redirect list ending
+ // at |cur_visit|.
+ void GetRedirectsToSpecificVisit(
+ VisitID cur_visit, history::RedirectList* redirects);
+
+ // Thumbnail Helpers ---------------------------------------------------------
+
+ // When a simple GetMostRecentRedirectsFrom() fails, this method is
+ // called which searches the last N visit sessions instead of just
+ // the current one. Returns true and puts thumbnail data in |data|
+ // if a proper thumbnail was found. Returns false otherwise. Assumes
+ // that this HistoryBackend object has been Init()ed successfully.
+ bool GetThumbnailFromOlderRedirect(
+ const GURL& page_url, std::vector<unsigned char>* data);
+
+ // Querying ------------------------------------------------------------------
+
+ // Backends for QueryHistory. *Basic() handles queries that are not FTS (full
+ // text search) queries and can just be given directly to the history DB).
+ // The FTS version queries the text_database, then merges with the history DB.
+ // Both functions assume QueryHistory already checked the DB for validity.
+ void QueryHistoryBasic(URLDatabase* url_db, VisitDatabase* visit_db,
+ const QueryOptions& options, QueryResults* result);
+ void QueryHistoryFTS(const string16& text_query,
+ const QueryOptions& options,
+ QueryResults* result);
+
+ // Committing ----------------------------------------------------------------
+
+ // We always keep a transaction open on the history database so that multiple
+ // transactions can be batched. Periodically, these are flushed (use
+ // ScheduleCommit). This function does the commit to write any new changes to
+ // disk and opens a new transaction. This will be called automatically by
+ // ScheduleCommit, or it can be called explicitly if a caller really wants
+ // to write something to disk.
+ void Commit();
+
+ // Schedules a commit to happen in the future. We do this so that many
+ // operations over a period of time will be batched together. If there is
+ // already a commit scheduled for the future, this will do nothing.
+ void ScheduleCommit();
+
+ // Cancels the scheduled commit, if any. If there is no scheduled commit,
+ // does nothing.
+ void CancelScheduledCommit();
+
+ // Segments ------------------------------------------------------------------
+
+ // Walks back a segment chain to find the last visit with a non null segment
+ // id and returns it. If there is none found, returns 0.
+ SegmentID GetLastSegmentID(VisitID from_visit);
+
+ // Update the segment information. This is called internally when a page is
+ // added. Return the segment id of the segment that has been updated.
+ SegmentID UpdateSegments(const GURL& url,
+ VisitID from_visit,
+ VisitID visit_id,
+ PageTransition::Type transition_type,
+ const base::Time ts);
+
+ // Favicons ------------------------------------------------------------------
+
+ // Used by both UpdateFavIconMappingAndFetch and GetFavIcon.
+ // If page_url is non-null and SetFavIcon has previously been invoked for
+ // icon_url the favicon url for page_url (and all redirects) is set to
+ // icon_url.
+ void UpdateFavIconMappingAndFetchImpl(
+ const GURL* page_url,
+ const GURL& icon_url,
+ scoped_refptr<GetFavIconRequest> request);
+
+ // Sets the favicon url id for page_url to id. This will also broadcast
+ // notifications as necessary.
+ void SetFavIconMapping(const GURL& page_url, FavIconID id);
+
+ // Generic stuff -------------------------------------------------------------
+
+ // Processes the next scheduled HistoryDBTask, scheduling this method
+ // to be invoked again if there are more tasks that need to run.
+ void ProcessDBTaskImpl();
+
+ // Release all tasks in history_db_tasks_ and clears it.
+ void ReleaseDBTasks();
+
+ // Schedules a broadcast of the given notification on the main thread. The
+ // details argument will have ownership taken by this function (it will be
+ // sent to the main thread and deleted there).
+ void BroadcastNotifications(NotificationType type,
+ HistoryDetails* details_deleted);
+
+ // Deleting all history ------------------------------------------------------
+
+ // Deletes all history. This is a special case of deleting that is separated
+ // from our normal dependency-following method for performance reasons. The
+ // logic lives here instead of ExpireHistoryBackend since it will cause
+ // re-initialization of some databases such as Thumbnails or Archived that
+ // could fail. When these databases are not valid, our pointers must be NULL,
+ // so we need to handle this type of operation to keep the pointers in sync.
+ void DeleteAllHistory();
+
+ // Given a vector of all URLs that we will keep, removes all thumbnails
+ // referenced by any URL, and also all favicons that aren't used by those
+ // URLs. The favicon IDs will change, so this will update the url rows in the
+ // vector to reference the new IDs.
+ bool ClearAllThumbnailHistory(std::vector<URLRow>* kept_urls);
+
+ // Deletes all information in the history database, except for the supplied
+ // set of URLs in the URL table (these should correspond to the bookmarked
+ // URLs).
+ //
+ // The IDs of the URLs may change.
+ bool ClearAllMainHistory(const std::vector<URLRow>& kept_urls);
+
+ // Returns the BookmarkService, blocking until it is loaded. This may return
+ // NULL during testing.
+ BookmarkService* GetBookmarkService();
+
+ // Data ----------------------------------------------------------------------
+
+ // Delegate. See the class definition above for more information. This will
+ // be NULL before Init is called and after Cleanup, but is guaranteed
+ // non-NULL in between.
+ scoped_ptr<Delegate> delegate_;
+
+ // Directory where database files will be stored.
+ FilePath history_dir_;
+
+ // The history/thumbnail databases. Either MAY BE NULL if the database could
+ // not be opened, all users must first check for NULL and return immediately
+ // if it is. The thumbnail DB may be NULL when the history one isn't, but not
+ // vice-versa.
+ scoped_ptr<HistoryDatabase> db_;
+ scoped_ptr<ThumbnailDatabase> thumbnail_db_;
+
+ // Stores old history in a larger, slower database.
+ scoped_ptr<ArchivedDatabase> archived_db_;
+
+ // Full text database manager, possibly NULL if the database could not be
+ // created.
+ scoped_ptr<TextDatabaseManager> text_database_;
+
+ // Manages expiration between the various databases.
+ ExpireHistoryBackend expirer_;
+
+ // A commit has been scheduled to occur sometime in the future. We can check
+ // non-null-ness to see if there is a commit scheduled in the future, and we
+ // can use the pointer to cancel the scheduled commit. There can be only one
+ // scheduled commit at a time (see ScheduleCommit).
+ scoped_refptr<CommitLaterTask> scheduled_commit_;
+
+ // Maps recent redirect destination pages to the chain of redirects that
+ // brought us to there. Pages that did not have redirects or were not the
+ // final redirect in a chain will not be in this list, as well as pages that
+ // redirected "too long" ago (as determined by ExpireOldRedirects above).
+ // It is used to set titles & favicons for redirects to that of the
+ // destination.
+ //
+ // As with AddPage, the last item in the redirect chain will be the
+ // destination of the redirect (i.e., the key into recent_redirects_);
+ typedef MRUCache<GURL, history::RedirectList> RedirectCache;
+ RedirectCache recent_redirects_;
+
+ // Timestamp of the last page addition request. We use this to detect when
+ // multiple additions are requested at the same time (within the resolution
+ // of the timer), so we can try to ensure they're unique when they're added
+ // to the database by using the last_recorded_time_ (q.v.). We still can't
+ // enforce or guarantee uniqueness, since the user might set his clock back.
+ base::Time last_requested_time_;
+
+ // Timestamp of the last page addition, as it was recorded in the database.
+ // If two or more requests come in at the same time, we increment that time
+ // by 1 us between them so it's more likely to be unique in the database.
+ // This keeps track of that higher-resolution timestamp.
+ base::Time last_recorded_time_;
+
+ // Timestamp of the first entry in our database.
+ base::Time first_recorded_time_;
+
+ // When non-NULL, this is the task that should be invoked on
+ MessageLoop* backend_destroy_message_loop_;
+ Task* backend_destroy_task_;
+
+ // Tracks page transition types.
+ VisitTracker tracker_;
+
+ // A boolean variable to track whether we have already purged obsolete segment
+ // data.
+ bool segment_queried_;
+
+ // HistoryDBTasks to run. Be sure to AddRef when adding, and Release when
+ // done.
+ std::list<HistoryDBTaskRequest*> db_task_requests_;
+
+ // Used to determine if a URL is bookmarked. This is owned by the Profile and
+ // may be NULL (during testing).
+ //
+ // Use GetBookmarkService to access this, which makes sure the service is
+ // loaded.
+ BookmarkService* bookmark_service_;
+
+ // Publishes the history to all indexers which are registered to receive
+ // history data from us. Can be NULL if there are no listeners.
+ scoped_ptr<HistoryPublisher> history_publisher_;
+
+ DISALLOW_COPY_AND_ASSIGN(HistoryBackend);
+};
+
+} // namespace history
+
+#endif // CHROME_BROWSER_HISTORY_HISTORY_BACKEND_H_