1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_backend.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <list> 872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <map> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <vector> 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/compiler_specific.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_vector.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/metrics/histogram.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/history_url_provider.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_service.h" 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/history/download_create_info.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_notifications.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_publisher.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/in_memory_history_backend.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/page_usage_data.h" 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/history/top_sites.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_constants.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/registry_controlled_domain.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* The HistoryBackend consists of a number of components: 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HistoryDatabase (stores past 3 months of history) 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLDatabase (stores a list of URLs) 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DownloadDatabase (stores a list of downloads) 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitDatabase (stores a list of visits for the URLs) 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitSegmentDatabase (stores groups of URLs for the most visited view). 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ArchivedDatabase (stores history older than 3 months) 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLDatabase (stores a list of URLs) 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DownloadDatabase (stores a list of downloads) 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitDatabase (stores a list of visits for the URLs) 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (this does not store visit segments as they expire after 3 mos.) 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextDatabaseManager (manages multiple text database for different times) 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TextDatabase (represents a single month of full-text index). 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ...more TextDatabase objects... 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExpireHistoryBackend (manages moving things from HistoryDatabase to 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch the ArchivedDatabase and deleting) 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch*/ 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace history { 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// How long we keep segment data for in days. Currently 3 months. 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This value needs to be greater or equal to 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// dependency between MostVisitedModel and the history backend. 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kSegmentDataRetention = 90; 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of milliseconds we'll wait to do a commit, so that things are 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// batched together. 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kCommitIntervalMs = 10000; 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The amount of time before we re-fetch the favicon. 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kFaviconRefetchDays = 7; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// GetSessionTabs returns all open tabs, or tabs closed kSessionCloseTimeWindow 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// seconds ago. 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kSessionCloseTimeWindowSecs = 10; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The maximum number of items we'll allow in the redirect list before 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// deleting some. 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMaxRedirectCount = 32; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of days old a history entry can be before it is considered "old" 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// and is archived. 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kArchiveDaysThreshold = 90; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Converts from PageUsageData to MostVisitedURL. |redirects| is a 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// list of redirects for this URL. Empty list means no redirects. 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const RedirectList& redirects) { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MostVisitedURL mv; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mv.url = page_data.GetURL(); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mv.title = page_data.GetTitle(); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (redirects.empty()) { 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Redirects must contain at least the target url. 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mv.redirects.push_back(mv.url); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mv.redirects = redirects; 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mv.redirects[mv.redirects.size() - 1] != mv.url) { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The last url must be the target url. 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mv.redirects.push_back(mv.url); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return mv; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This task is run on a timer so that commits happen at regular intervals 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// so they are batched together. The important thing about this class is that 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// it supports canceling of the task so the reference to the backend will be 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// freed. The problem is that when history is shutting down, there is likely 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to be one of these commits still pending and holding a reference. 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The backend can call Cancel to have this task release the reference. The 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// task will still run (if we ever get to processing the event before 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// shutdown), but it will not do anything. 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Note that this is a refcounted object and is not a task in itself. It should 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// be assigned to a RunnableMethod. 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(brettw): bug 1165182: This should be replaced with a 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ScopedRunnableMethodFactory which will handle everything automatically (like 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// we do in ExpireHistoryBackend). 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CommitLaterTask : public base::RefCounted<CommitLaterTask> { 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit CommitLaterTask(HistoryBackend* history_backend) 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : history_backend_(history_backend) { 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The backend will call this function if it is being destroyed so that we 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // release our reference. 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Cancel() { 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_backend_ = NULL; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void RunCommit() { 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (history_backend_.get()) 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_backend_->Commit(); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class base::RefCounted<CommitLaterTask>; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~CommitLaterTask() {} 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<HistoryBackend> history_backend_; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Handles querying first the main database, then the full text database if that 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// fails. It will optionally keep track of all URLs seen so duplicates can be 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// eliminated. This is used by the querying sub-functions. 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(brettw): This class may be able to be simplified or eliminated. After 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// this was written, QueryResults can efficiently look up by URL, so the need 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// for this extra set of previously queried URLs is less important. 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass HistoryBackend::URLQuerier { 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLQuerier(URLDatabase* main_db, URLDatabase* archived_db, bool track_unique) 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : main_db_(main_db), 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_(archived_db), 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch track_unique_(track_unique) { 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we're tracking unique URLs, returns true if this URL has been 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // previously queried. Only call when tracking unique URLs. 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool HasURL(const GURL& url) { 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(track_unique_); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return unique_urls_.find(url) != unique_urls_.end(); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool GetRowForURL(const GURL& url, URLRow* row) { 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!main_db_->GetRowForURL(url, row)) { 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!archived_db_ || !archived_db_->GetRowForURL(url, row)) { 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This row is neither in the main nor the archived DB. 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (track_unique_) 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch unique_urls_.insert(url); 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLDatabase* main_db_; // Guaranteed non-NULL. 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLDatabase* archived_db_; // Possibly NULL. 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool track_unique_; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When track_unique_ is set, this is updated with every URL seen so far. 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<GURL> unique_urls_; 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(URLQuerier); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HistoryBackend -------------------------------------------------------------- 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHistoryBackend::HistoryBackend(const FilePath& history_dir, 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Delegate* delegate, 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkService* bookmark_service) 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : delegate_(delegate), 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_dir_(history_dir), 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(expirer_(this, bookmark_service)), 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch recent_redirects_(kMaxRedirectCount), 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch backend_destroy_message_loop_(NULL), 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch backend_destroy_task_(NULL), 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch segment_queried_(false), 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_service_(bookmark_service) { 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHistoryBackend::~HistoryBackend() { 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!scheduled_commit_) << "Deleting without cleanup"; 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReleaseDBTasks(); 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First close the databases before optionally running the "destroy" task. 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Commit the long-running transaction. 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->CommitTransaction(); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_.reset(); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (thumbnail_db_.get()) { 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_->CommitTransaction(); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_.reset(); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (archived_db_.get()) { 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_->CommitTransaction(); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_.reset(); 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_database_.get()) { 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->CommitTransaction(); 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_.reset(); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (backend_destroy_task_) { 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notify an interested party (typically a unit test) that we're done. 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(backend_destroy_message_loop_); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch backend_destroy_message_loop_->PostTask(FROM_HERE, backend_destroy_task_); 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 244731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid HistoryBackend::Init(const std::string& languages, bool force_fail) { 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!force_fail) 246731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick InitImpl(languages); 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->DBLoaded(); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::SetOnBackendDestroyTask(MessageLoop* message_loop, 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Task* task) { 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (backend_destroy_task_) { 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DLOG(WARNING) << "Setting more than one destroy task, overriding"; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete backend_destroy_task_; 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch backend_destroy_message_loop_ = message_loop; 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch backend_destroy_task_ = task; 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::Closing() { 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Any scheduled commit will have a reference to us, we must make it 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // release that reference before we can be destroyed. 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CancelScheduledCommit(); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Release our reference to the delegate, this reference will be keeping the 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // history service alive. 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_.reset(); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::NotifyRenderProcessHostDestruction(const void* host) { 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracker_.NotifyRenderProcessHostDestruction(host); 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFilePath HistoryBackend::GetThumbnailFileName() const { 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return history_dir_.Append(chrome::kThumbnailsFilename); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFilePath HistoryBackend::GetFaviconsFileName() const { 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return history_dir_.Append(chrome::kFaviconsFilename); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFilePath HistoryBackend::GetArchivedFileName() const { 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return history_dir_.Append(chrome::kArchivedHistoryFilename); 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSegmentID HistoryBackend::GetLastSegmentID(VisitID from_visit) { 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set is used to detect referrer loops. Should not happen, but can 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if the database is corrupt. 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<VisitID> visit_set; 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitID visit_id = from_visit; 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (visit_id) { 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitRow row; 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->GetRowForVisit(visit_id, &row)) 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (row.segment_id) 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return row.segment_id; // Found a visit in this change with a segment. 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check the referrer of this visit, if any. 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_id = row.referring_visit; 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visit_set.find(visit_id) != visit_set.end()) { 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Loop in referer chain, giving up"; 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_set.insert(visit_id); 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSegmentID HistoryBackend::UpdateSegments(const GURL& url, 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitID from_visit, 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitID visit_id, 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type transition_type, 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Time ts) { 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We only consider main frames. 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!PageTransition::IsMainFrame(transition_type)) 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SegmentID segment_id = 0; 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type t = PageTransition::StripQualifier(transition_type); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Are we at the beginning of a new segment? 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (t == PageTransition::TYPED || t == PageTransition::AUTO_BOOKMARK) { 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If so, create or get the segment. 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string segment_name = db_->ComputeSegmentName(url); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID url_id = db_->GetRowForURL(url, NULL); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url_id) 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(segment_id = db_->GetSegmentNamed(segment_name))) { 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(segment_id = db_->CreateSegment(url_id, segment_name))) { 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: if we update an existing segment, we update the url used to 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // represent that segment in order to minimize stale most visited 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // images. 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->UpdateSegmentRepresentationURL(segment_id, url_id); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: it is possible there is no segment ID set for this visit chain. 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This can happen if the initial navigation wasn't AUTO_BOOKMARK or 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TYPED. (For example GENERATED). In this case this visit doesn't count 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // toward any segment. 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(segment_id = GetLastSegmentID(from_visit))) 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the segment in the visit. 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->SetSegmentID(visit_id, segment_id)) { 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Finally, increase the counter for that segment / day. 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->IncreaseSegmentVisitCount(segment_id, ts, 1)) { 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return segment_id; 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::AddPage(scoped_refptr<HistoryAddPageArgs> request) { 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Will be filled with the URL ID and the visit ID of the last addition. 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::pair<URLID, VisitID> last_ids(0, tracker_.GetLastVisit( 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->id_scope, request->page_id, request->referrer)); 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitID from_visit_id = last_ids.second; 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If a redirect chain is given, we expect the last item in that chain to be 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the final URL. 379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(request->redirects.empty() || 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->redirects.back() == request->url); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Avoid duplicating times in the database, at least as long as pages are 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // added in order. However, we don't want to disallow pages from recording 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // times earlier than our last_recorded_time_, because someone might set 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // their machine's clock back. 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (last_requested_time_ == request->time) { 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_recorded_time_ = last_recorded_time_ + TimeDelta::FromMicroseconds(1); 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_requested_time_ = request->time; 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_recorded_time_ = last_requested_time_; 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the user is adding older history, we need to make sure our times 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // are correct. 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->time < first_recorded_time_) 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch first_recorded_time_ = request->time; 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type transition = 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::StripQualifier(request->transition); 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_keyword_generated = (transition == PageTransition::KEYWORD_GENERATED); 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->redirects.size() <= 1) { 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The single entry is both a chain start and end. 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type t = request->transition | 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::CHAIN_START | PageTransition::CHAIN_END; 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No redirect case (one element means just the page itself). 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_ids = AddPageVisit(request->url, last_recorded_time_, 4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick last_ids.second, t, request->visit_source); 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the segment for this visit. KEYWORD_GENERATED visits should not 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // result in changing most visited, so we don't update segments (most 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // visited db). 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!is_keyword_generated) { 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateSegments(request->url, from_visit_id, last_ids.second, t, 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_recorded_time_); 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Redirect case. Add the redirect chain. 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type redirect_info = PageTransition::CHAIN_START; 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->redirects[0].SchemeIs(chrome::kAboutScheme)) { 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the redirect source + referrer is "about" we skip it. This 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // happens when a page opens a new frame/window to about:blank and then 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // script sets the URL to somewhere else (used to hide the referrer). It 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // would be nice to keep all these redirects properly but we don't ever 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // see the initial about:blank load, so we don't know where the 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // subsequent client redirect came from. 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // In this case, we just don't bother hooking up the source of the 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // redirects, so we remove it. 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->redirects.erase(request->redirects.begin()); 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (request->transition & PageTransition::CLIENT_REDIRECT) { 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirect_info = PageTransition::CLIENT_REDIRECT; 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The first entry in the redirect chain initiated a client redirect. 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't add this to the database since the referrer is already 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // there, so we skip over it but change the transition type of the first 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // transition to client redirect. 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The referrer is invalid when restoring a session that features an 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // https tab that redirects to a different host or to http. In this 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // case we don't need to reconnect the new redirect with the existing 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // chain. 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->referrer.is_valid()) { 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(request->referrer == request->redirects[0]); 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->redirects.erase(request->redirects.begin()); 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the navigation entry for this visit has replaced that for the 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // first visit, remove the CHAIN_END marker from the first visit. This 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // can be called a lot, for example, the page cycler, and most of the 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time we won't have changed anything. 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitRow visit_row; 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->did_replace_entry && 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetRowForVisit(last_ids.second, &visit_row) && 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_row.transition | PageTransition::CHAIN_END) { 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_row.transition &= ~PageTransition::CHAIN_END; 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->UpdateVisitRow(visit_row); 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t redirect_index = 0; redirect_index < request->redirects.size(); 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirect_index++) { 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type t = transition | redirect_info; 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If this is the last transition, add a CHAIN_END marker 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (redirect_index == (request->redirects.size() - 1)) 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch t = t | PageTransition::CHAIN_END; 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Record all redirect visits with the same timestamp. We don't display 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // them anyway, and if we ever decide to, we can reconstruct their order 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from the redirect chain. 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_ids = AddPageVisit(request->redirects[redirect_index], 4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick last_recorded_time_, last_ids.second, 4763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick t, request->visit_source); 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (t & PageTransition::CHAIN_START) { 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the segment for this visit. 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateSegments(request->redirects[redirect_index], 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch from_visit_id, last_ids.second, t, last_recorded_time_); 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Subsequent transitions in the redirect list must all be sever 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // redirects. 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirect_info = PageTransition::SERVER_REDIRECT; 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Last, save this redirect chain for later so we can set titles & favicons 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // on the redirected pages properly. It is indexed by the destination page. 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch recent_redirects_.Put(request->url, request->redirects); 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(brettw) bug 1140015: Add an "add page" notification so the history 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // views can keep in sync. 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add the last visit to the tracker so we can get outgoing transitions. 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(evanm): Due to http://b/1194536 we lose the referrers of a subframe 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // navigation anyway, so last_visit_id is always zero for them. But adding 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // them here confuses main frame history, so we skip them for now. 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (transition != PageTransition::AUTO_SUBFRAME && 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transition != PageTransition::MANUAL_SUBFRAME && !is_keyword_generated) { 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracker_.AddVisit(request->id_scope, request->page_id, request->url, 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_ids.second); 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_database_.get()) { 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->AddPageURL(request->url, last_ids.first, last_ids.second, 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_recorded_time_); 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 514731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid HistoryBackend::InitImpl(const std::string& languages) { 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!db_.get()) << "Initializing HistoryBackend twice"; 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // In the rare case where the db fails to initialize a dialog may get shown 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the blocks the caller, yet allows other messages through. For this reason 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we only set db_ to the created database if creation is successful. That 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // way other methods won't do anything as db_ is still NULL. 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks beginning_time = TimeTicks::Now(); 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compute the file names. Note that the index file can be removed when the 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // text db manager is finished being hooked up. 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath history_name = history_dir_.Append(chrome::kHistoryFilename); 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath thumbnail_name = GetThumbnailFileName(); 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath archived_name = GetArchivedFileName(); 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath tmp_bookmarks_file = history_dir_.Append( 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::kHistoryBookmarksFileName); 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // History database. 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_.reset(new HistoryDatabase()); 533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sql::InitStatus status = db_->Init(history_name, tmp_bookmarks_file); 534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switch (status) { 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case sql::INIT_OK: 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case sql::INIT_FAILURE: 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A NULL db_ will cause all calls on this object to notice this error 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and to not continue. 540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate_->NotifyProfileError(status); 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_.reset(); 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Fill the in-memory database and send it back to the history service on the 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // main thread. 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InMemoryHistoryBackend* mem_backend = new InMemoryHistoryBackend; 550dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (mem_backend->Init(history_name, history_dir_, db_.get(), languages)) 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->SetInMemoryBackend(mem_backend); // Takes ownership of pointer. 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete mem_backend; // Error case, run without the in-memory DB. 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->BeginExclusiveMode(); // Must be after the mem backend read the data. 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create the history publisher which needs to be passed on to the text and 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // thumbnail databases for publishing history. 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_publisher_.reset(new HistoryPublisher()); 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!history_publisher_->Init()) { 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The init may fail when there are no indexers wanting our history. 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Hence no need to log the failure. 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_publisher_.reset(); 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Full-text database. This has to be first so we can pass it to the 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // HistoryDatabase for migration. 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_.reset(new TextDatabaseManager(history_dir_, 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_.get(), db_.get())); 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!text_database_->Init(history_publisher_.get())) { 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "Text database initialization failed, running without it."; 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_.reset(); 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_->needs_version_17_migration()) { 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See needs_version_17_migration() decl for more. In this case, we want 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to erase all the text database files. This must be done after the text 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // database manager has been initialized, since it knows about all the 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // files it manages. 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->DeleteAll(); 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Thumbnail database. 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_.reset(new ThumbnailDatabase()); 58372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!db_->GetNeedsThumbnailMigration()) { 5843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // No convertion needed - use new filename right away. 585513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch thumbnail_name = GetFaviconsFileName(); 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (thumbnail_db_->Init(thumbnail_name, 588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen history_publisher_.get(), 589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen db_.get()) != sql::INIT_OK) { 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unlike the main database, we don't error out when the database is too 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // new because this error is much less severe. Generally, this shouldn't 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // happen since the thumbnail and main datbase versions should be in sync. 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We'll just continue without thumbnails & favicons in this case or any 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // other error. 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "Could not initialize the thumbnail database."; 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_.reset(); 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (db_->GetNeedsThumbnailMigration()) { 600513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "Starting TopSites migration"; 601513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch delegate_->StartTopSitesMigration(); 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Archived database. 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_->needs_version_17_migration()) { 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See needs_version_17_migration() decl for more. In this case, we want 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to delete the archived database and need to do so before we try to 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // open the file. We can ignore any error (maybe the file doesn't exist). 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_util::Delete(archived_name, false); 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_.reset(new ArchivedDatabase()); 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!archived_db_->Init(archived_name)) { 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "Could not initialize the archived database."; 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_.reset(); 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tell the expiration module about all the nice databases we made. This must 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // happen before db_->Init() is called since the callback ForceArchiveHistory 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // may need to expire stuff. 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // *sigh*, this can all be cleaned up when that migration code is removed. 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The main DB initialization should intuitively be first (not that it 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // actually matters) and the expirer should be set last. 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expirer_.SetDatabases(db_.get(), archived_db_.get(), 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_.get(), text_database_.get()); 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Open the long-running transaction. 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->BeginTransaction(); 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (thumbnail_db_.get()) 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_->BeginTransaction(); 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (archived_db_.get()) 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_->BeginTransaction(); 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_database_.get()) 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->BeginTransaction(); 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get the first item in our database. 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetStartDate(&first_recorded_time_); 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Start expiring old stuff. 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expirer_.StartArchivingOldStuff(TimeDelta::FromDays(kArchiveDaysThreshold)); 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HISTOGRAM_TIMES("History.InitTime", 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks::Now() - beginning_time); 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::pair<URLID, VisitID> HistoryBackend::AddPageVisit( 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time time, 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitID referring_visit, 6503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PageTransition::Type transition, 6513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick VisitSource visit_source) { 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Top-level frame navigations are visible, everything else is hidden 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool new_hidden = !PageTransition::IsMainFrame(transition); 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NOTE: This code must stay in sync with 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ExpireHistoryBackend::ExpireURLsForVisits(). 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(pkasting): http://b/1148304 We shouldn't be marking so many URLs as 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // typed, which would eliminate the need for this code. 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int typed_increment = 0; 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type transition_type = 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::StripQualifier(transition); 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((transition_type == PageTransition::TYPED && 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !PageTransition::IsRedirect(transition)) || 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transition_type == PageTransition::KEYWORD_GENERATED) 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_increment = 1; 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See if this URL is already in the DB. 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow url_info(url); 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID url_id = db_->GetRowForURL(url, &url_info); 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url_id) { 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update of an existing row. 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (PageTransition::StripQualifier(transition) != PageTransition::RELOAD) 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_visit_count(url_info.visit_count() + 1); 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (typed_increment) 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_typed_count(url_info.typed_count() + typed_increment); 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_last_visit(time); 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only allow un-hiding of pages, never hiding. 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!new_hidden) 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_hidden(false); 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->UpdateURLRow(url_id, url_info); 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Addition of a new row. 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_visit_count(1); 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_typed_count(typed_increment); 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_last_visit(time); 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_hidden(new_hidden); 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_id = db_->AddURL(url_info); 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url_id) { 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Adding URL failed."; 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return std::make_pair(0, 0); 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.id_ = url_id; 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't actually add the URL to the full text index at this point. It 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // might be nice to do this so that even if we get no title or body, the 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // user can search for URL components and get the page. 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // However, in most cases, we'll get at least a title and usually contents, 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and this add will be redundant, slowing everything down. As a result, 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we ignore this edge case. 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add the visit with the time to the database. 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitRow visit_info(url_id, time, referring_visit, transition, 0); 7083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick VisitID visit_id = db_->AddVisit(&visit_info, visit_source); 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visit_info.visit_time < first_recorded_time_) 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch first_recorded_time_ = visit_info.visit_time; 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Broadcast a notification of the visit. 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visit_id) { 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLVisitedDetails* details = new URLVisitedDetails; 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch details->transition = transition; 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch details->row = url_info; 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(meelapshah) Disabled due to potential PageCycler regression. 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Re-enable this. 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GetMostRecentRedirectsTo(url, &details->redirects); 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastNotifications(NotificationType::HISTORY_URL_VISITED, details); 72272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 72372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen VLOG(0) << "Failed to build visit insert statement: " 72472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << "url_id = " << url_id; 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return std::make_pair(url_id, visit_id); 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HistoryBackend::AddPagesWithDetails(const std::vector<URLRow>& urls, 7313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick VisitSource visit_source) { 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<URLsModifiedDetails> modified(new URLsModifiedDetails); 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<URLRow>::const_iterator i = urls.begin(); 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != urls.end(); ++i) { 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!i->last_visit().is_null()); 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We will add to either the archived database or the main one depending on 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the date of the added visit. 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLDatabase* url_database; 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitDatabase* visit_database; 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i->last_visit() < expirer_.GetCurrentArchiveTime()) { 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!archived_db_.get()) 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // No archived database to save it to, just forget this. 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_database = archived_db_.get(); 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_database = archived_db_.get(); 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_database = db_.get(); 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_database = db_.get(); 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow existing_url; 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID url_id = url_database->GetRowForURL(i->url(), &existing_url); 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url_id) { 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add the page if it doesn't exist. 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_id = url_database->AddURL(*i); 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url_id) { 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Could not add row to DB"; 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (i->typed_count() > 0) 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch modified->changed_urls.push_back(*i); 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add the page to the full text index. This function is also used for 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // importing. Even though we don't have page contents, we can at least 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // add the title and URL to the index so they can be searched. We don't 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bother to delete any already-existing FTS entries for the URL, since 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this is normally called on import. 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If you ever import *after* first run (selecting import from the menu), 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // then these additional entries will "shadow" the originals when querying 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for the most recent match only, and the user won't get snippets. This is 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a very minor issue, and fixing it will make import slower, so we don't 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bother. 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_indexed = false; 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_database_.get()) { 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We do not have to make it update the visit database, below, we will 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // create the visit entry with the indexed flag set. 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_indexed = text_database_->AddPageData(i->url(), url_id, 0, 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i->last_visit(), 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i->title(), string16()); 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make up a visit to correspond to that page. 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitRow visit_info(url_id, i->last_visit(), 0, 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::LINK | PageTransition::CHAIN_START | 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::CHAIN_END, 0); 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_info.is_indexed = has_indexed; 7933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!visit_database->AddVisit(&visit_info, visit_source)) { 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Adding visit failed."; 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visit_info.visit_time < first_recorded_time_) 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch first_recorded_time_ = visit_info.visit_time; 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Broadcast a notification for typed URLs that have been modified. This 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will be picked up by the in-memory URL database on the main thread. 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(brettw) bug 1140015: Add an "add page" notification so the history 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // views can keep in sync. 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastNotifications(NotificationType::HISTORY_TYPED_URLS_MODIFIED, 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch modified.release()); 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::SetPageTitle(const GURL& url, 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string16& title) { 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Search for recent redirects which should get the same title. We make a 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // dummy list containing the exact URL visited if there are no redirects so 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the processing below can be the same. 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectList dummy_list; 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectList* redirects; 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RedirectCache::iterator iter = recent_redirects_.Get(url); 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (iter != recent_redirects_.end()) { 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirects = &iter->second; 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This redirect chain should have the destination URL as the last item. 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!redirects->empty()); 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(redirects->back() == url); 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No redirect chain stored, make up one containing the URL we want so we 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // can use the same logic below. 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dummy_list.push_back(url); 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirects = &dummy_list; 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool typed_url_changed = false; 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<URLRow> changed_urls; 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < redirects->size(); i++) { 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow row; 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID row_id = db_->GetRowForURL(redirects->at(i), &row); 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (row_id && row.title() != title) { 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch row.set_title(title); 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->UpdateURLRow(row_id, row); 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed_urls.push_back(row); 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (row.typed_count() > 0) 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typed_url_changed = true; 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Broadcast notifications for typed URLs that have changed. This will 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // update the in-memory database. 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(brettw) bug 1140020: Broadcast for all changes (not just typed), 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in which case some logic can be removed. 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (typed_url_changed) { 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLsModifiedDetails* modified = 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new URLsModifiedDetails; 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < changed_urls.size(); i++) { 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (changed_urls[i].typed_count() > 0) 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch modified->changed_urls.push_back(changed_urls[i]); 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastNotifications(NotificationType::HISTORY_TYPED_URLS_MODIFIED, 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch modified); 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update the full text index. 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_database_.get()) 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->AddPageTitle(url, title); 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only bother committing if things changed. 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!changed_urls.empty()) 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid HistoryBackend::AddPageNoVisitForBookmark(const GURL& url) { 87721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!db_.get()) 87821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 87921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 88021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen URLRow url_info(url); 88121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen URLID url_id = db_->GetRowForURL(url, &url_info); 88221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (url_id) { 88321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // URL is already known, nothing to do. 88421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 88521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 88621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen url_info.set_last_visit(Time::Now()); 88721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Mark the page hidden. If the user types it in, it'll unhide. 88821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen url_info.set_hidden(true); 88921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 89021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen db_->AddURL(url_info); 89121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 89221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::IterateURLs(HistoryService::URLEnumerator* iterator) { 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HistoryDatabase::URLEnumerator e; 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_->InitURLEnumeratorForEverything(&e)) { 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow info; 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (e.GetNextURL(&info)) { 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iterator->OnURL(info.url()); 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iterator->OnComplete(true); // Success. 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iterator->OnComplete(false); // Failure. 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::GetAllTypedURLs(std::vector<history::URLRow>* urls) { 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return db_->GetAllTypedUrls(urls); 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::GetVisitsForURL(URLID id, VisitVector* visits) { 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return db_->GetVisitsForURL(id, visits); 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::UpdateURL(URLID id, const history::URLRow& url) { 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return db_->UpdateURLRow(id, url); 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::AddVisits(const GURL& url, 9273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::vector<base::Time>& visits, 9283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick VisitSource visit_source) { 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<base::Time>::const_iterator visit = visits.begin(); 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit != visits.end(); ++visit) { 9323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!AddPageVisit(url, *visit, 0, 0, visit_source).first) { 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::RemoveVisits(const VisitVector& visits) { 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<URLID, int> url_visits_removed; 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (VisitVector::const_iterator visit = visits.begin(); 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit != visits.end(); ++visit) { 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->DeleteVisit(*visit); 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<URLID, int>::iterator visit_count = 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_visits_removed.find(visit->url_id); 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visit_count == url_visits_removed.end()) { 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_visits_removed[visit->url_id] = 1; 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++visit_count->second; 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::map<URLID, int>::iterator count = url_visits_removed.begin(); 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch count != url_visits_removed.end(); ++count) { 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::URLRow url_row; 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->GetURLRow(count->first, &url_row)) { 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(count->second <= url_row.visit_count()); 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_row.set_visit_count(url_row.visit_count() - count->second); 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->UpdateURLRow(url_row.id(), url_row)) { 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::GetURL(const GURL& url, history::URLRow* url_row) { 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return db_->GetRowForURL(url, url_row) != 0; 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QueryURL(scoped_refptr<QueryURLRequest> request, 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool want_visits) { 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = false; 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow* row = &request->value.a; 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector* visits = &request->value.b; 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_->GetRowForURL(url, row)) { 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Have a row. 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = true; 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Optionally query the visits. 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (want_visits) 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetVisitsForURL(row->id(), visits); 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(QueryURLRequest::TupleType(request->handle(), success, 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch row, visits)); 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Segment usage --------------------------------------------------------------- 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::DeleteOldSegmentData() { 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->DeleteSegmentData(Time::Now() - 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta::FromDays(kSegmentDataRetention)); 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::SetSegmentPresentationIndex(SegmentID segment_id, 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->SetSegmentPresentationIndex(segment_id, index); 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QuerySegmentUsage( 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<QuerySegmentUsageRequest> request, 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Time from_time, 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int max_result_count) { 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->QuerySegmentUsage(from_time, max_result_count, &request->value.get()); 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If this is the first time we query segments, invoke 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // DeleteOldSegmentData asynchronously. We do this to cleanup old 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // entries. 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!segment_queried_) { 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch segment_queried_ = true; 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostTask(FROM_HERE, 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &HistoryBackend::DeleteOldSegmentData)); 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult( 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QuerySegmentUsageRequest::TupleType(request->handle(), 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &request->value.get())); 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Keyword visits -------------------------------------------------------------- 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::SetKeywordSearchTermsForURL(const GURL& url, 10443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TemplateURLID keyword_id, 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string16& term) { 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get the ID for this URL. 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow url_row; 1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->GetRowForURL(url, &url_row)) { 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // There is a small possibility the url was deleted before the keyword 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // was added. Ignore the request. 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->SetKeywordSearchTermsForURL(url_row.id(), keyword_id, term); 1058513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1059513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // details is deleted by BroadcastNotifications. 1060513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch KeywordSearchTermDetails* details = new KeywordSearchTermDetails; 1061513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch details->url = url; 1062513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch details->keyword_id = keyword_id; 1063513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch details->term = term; 1064513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch BroadcastNotifications(NotificationType::HISTORY_KEYWORD_SEARCH_TERM_UPDATED, 1065513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch details); 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::DeleteAllSearchTermsForKeyword( 10703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TemplateURLID keyword_id) { 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->DeleteAllSearchTermsForKeyword(keyword_id); 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(sky): bug 1168470. Need to move from archive dbs too. 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::GetMostRecentKeywordSearchTerms( 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request, 10813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TemplateURLID keyword_id, 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string16& prefix, 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int max_count) { 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetMostRecentKeywordSearchTerms(keyword_id, prefix, max_count, 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &(request->value)); 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult( 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetMostRecentKeywordSearchTermsRequest::TupleType(request->handle(), 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &request->value)); 1094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Downloads ------------------------------------------------------------------- 1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Get all the download entries from the database. 1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QueryDownloads( 1100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<DownloadQueryRequest> request) { 1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->QueryDownloads(&request->value); 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(DownloadQueryRequest::TupleType(&request->value)); 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Clean up entries that has been corrupted (because of the crash, for example). 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::CleanUpInProgressEntries() { 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If some "in progress" entries were not updated when Chrome exited, they 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // need to be cleaned up. 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->CleanUpInProgressEntries(); 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Update a particular download entry. 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::UpdateDownload(int64 received_bytes, 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 state, 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 db_handle) { 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->UpdateDownload(received_bytes, state, db_handle); 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Update the path of a particular download entry. 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::UpdateDownloadPath(const FilePath& path, 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 db_handle) { 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->UpdateDownloadPath(path, db_handle); 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Create a new download entry and pass back the db_handle to it. 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::CreateDownload( 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<DownloadCreateRequest> request, 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DownloadCreateInfo& create_info) { 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 db_handle = 0; 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!request->canceled()) { 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_handle = db_->CreateDownload(create_info); 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(DownloadCreateRequest::TupleType(create_info, 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_handle)); 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::RemoveDownload(int64 db_handle) { 1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->RemoveDownload(db_handle); 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::RemoveDownloadsBetween(const Time remove_begin, 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Time remove_end) { 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) 1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->RemoveDownloadsBetween(remove_begin, remove_end); 1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QueryHistory(scoped_refptr<QueryHistoryRequest> request, 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string16& text_query, 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const QueryOptions& options) { 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks beginning_time = TimeTicks::Now(); 1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_query.empty()) { 1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Basic history query for the main database. 1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QueryHistoryBasic(db_.get(), db_.get(), options, &request->value); 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now query the archived database. This is a bit tricky because we don't 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // want to query it if the queried time range isn't going to find anything 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // in it. 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(brettw) bug 1171036: do blimpie querying for the archived database 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // as well. 1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if (archived_db_.get() && 1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // expirer_.GetCurrentArchiveTime() - TimeDelta::FromDays(7)) { 1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Full text history query. 1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QueryHistoryFTS(text_query, options, &request->value); 1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(QueryHistoryRequest::TupleType(request->handle(), 1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &request->value)); 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_TIMES("History.QueryHistory", 1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks::Now() - beginning_time); 1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Basic time-based querying of history. 1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QueryHistoryBasic(URLDatabase* url_db, 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitDatabase* visit_db, 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const QueryOptions& options, 1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QueryResults* result) { 1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First get all visits. 1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector visits; 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_db->GetVisibleVisitsInRange(options.begin_time, options.end_time, 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch options.max_count, &visits); 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(options.max_count == 0 || 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(visits.size()) <= options.max_count); 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now add them and the URL rows to the results. 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLResult url_result; 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < visits.size(); i++) { 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const VisitRow visit = visits[i]; 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add a result row for this visit, get the URL info from the DB. 120772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!url_db->GetURLRow(visit.url_id, &url_result)) { 120872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen VLOG(0) << "Failed to get id " << visit.url_id 120972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << " from history.urls."; 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; // DB out of sync and URL doesn't exist, try to recover. 121172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 121272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 121372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!url_result.url().is_valid()) { 121472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen VLOG(0) << "Got invalid URL from history.urls with id " 121572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << visit.url_id << ": " 121672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << url_result.url().possibly_invalid_spec(); 1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; // Don't report invalid URLs in case of corruption. 121872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The archived database may be out of sync with respect to starring, 1221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // titles, last visit date, etc. Therefore, we query the main DB if the 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // current URL database is not the main one. 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url_db == db_.get()) { 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Currently querying the archived DB, update with the main database to 1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // catch any interesting stuff. This will update it if it exists in the 1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // main DB, and do nothing otherwise. 1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetRowForURL(url_result.url(), &url_result); 1228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_result.set_visit_time(visit.visit_time); 1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't set any of the query-specific parts of the URLResult, since 1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // snippets and stuff don't apply to basic querying. 1234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->AppendURLBySwapping(&url_result); 1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (options.begin_time <= first_recorded_time_) 1238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->set_reached_beginning(true); 1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QueryHistoryFTS(const string16& text_query, 1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const QueryOptions& options, 1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QueryResults* result) { 1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!text_database_.get()) 1245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Full text query, first get all the FTS results in the time range. 1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<TextDatabase::Match> fts_matches; 1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time first_time_searched; 1250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->GetTextMatches(text_query, options, 1251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &fts_matches, &first_time_searched); 1252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLQuerier querier(db_.get(), archived_db_.get(), true); 1254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now get the row and visit information for each one. 1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLResult url_result; // Declare outside loop to prevent re-construction. 1257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < fts_matches.size(); i++) { 1258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (options.max_count != 0 && 1259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(result->size()) >= options.max_count) 1260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; // Got too many items. 1261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get the URL, querying the main and archived databases as necessary. If 1263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this is not found, the history and full text search databases are out 1264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of sync and we give up with this result. 1265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!querier.GetRowForURL(fts_matches[i].url, &url_result)) 1266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 1267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url_result.url().is_valid()) 1269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; // Don't report invalid URLs in case of corruption. 1270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy over the FTS stuff that the URLDatabase doesn't know about. 1272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We do this with swap() to avoid copying, since we know we don't 1273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // need the original any more. Note that we override the title with the 1274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // one from FTS, since that will match the title_match_positions (the 1275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // FTS title and the history DB title may differ). 1276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_result.set_title(fts_matches[i].title); 1277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_result.title_match_positions_.swap( 1278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fts_matches[i].title_match_positions); 1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_result.snippet_.Swap(&fts_matches[i].snippet); 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The visit time also comes from the full text search database. Since it 1282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // has the time, we can avoid an extra query of the visits table. 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_result.set_visit_time(fts_matches[i].time); 1284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add it to the vector, this will clear our |url_row| object as a 1286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // result of the swap. 1287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->AppendURLBySwapping(&url_result); 1288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (options.begin_time <= first_recorded_time_) 1291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->set_reached_beginning(true); 1292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Frontend to GetMostRecentRedirectsFrom from the history thread. 1295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QueryRedirectsFrom( 1296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<QueryRedirectsRequest> request, 1297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url) { 1298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = GetMostRecentRedirectsFrom(url, &request->value); 1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(QueryRedirectsRequest::TupleType( 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->handle(), url, success, &request->value)); 1303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QueryRedirectsTo( 1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<QueryRedirectsRequest> request, 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url) { 1308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = GetMostRecentRedirectsTo(url, &request->value); 1311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(QueryRedirectsRequest::TupleType( 1312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->handle(), url, success, &request->value)); 1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::GetVisitCountToHost( 1316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<GetVisitCountToHostRequest> request, 1317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url) { 1318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int count = 0; 1321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time first_visit; 1322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool success = (db_.get() && db_->GetVisitCountToHost(url, &count, 1323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &first_visit)); 1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(GetVisitCountToHostRequest::TupleType( 1325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->handle(), success, count, first_visit)); 1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QueryTopURLsAndRedirects( 1329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<QueryTopURLsAndRedirectsRequest> request, 1330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int result_count) { 1331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) { 1335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(QueryTopURLsAndRedirectsRequest::TupleType( 1336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->handle(), false, NULL, NULL)); 1337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<GURL>* top_urls = &request->value.a; 1341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectMap* redirects = &request->value.b; 1342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedVector<PageUsageData> data; 1344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->QuerySegmentUsage(base::Time::Now() - base::TimeDelta::FromDays(90), 1345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_count, &data.get()); 1346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < data.size(); ++i) { 1348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch top_urls->push_back(data[i]->GetURL()); 1349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RefCountedVector<GURL>* list = new RefCountedVector<GURL>; 1350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetMostRecentRedirectsFrom(top_urls->back(), &list->data); 1351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*redirects)[top_urls->back()] = list; 1352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(QueryTopURLsAndRedirectsRequest::TupleType( 1355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->handle(), true, top_urls, redirects)); 1356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Will replace QueryTopURLsAndRedirectsRequest. 1359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::QueryMostVisitedURLs( 1360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<QueryMostVisitedURLsRequest> request, 1361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int result_count, 1362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int days_back) { 1363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) { 1367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No History Database - return an empty list. 1368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(QueryMostVisitedURLsRequest::TupleType( 1369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->handle(), MostVisitedURLList())); 1370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MostVisitedURLList* result = &request->value; 1374513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch QueryMostVisitedURLsImpl(result_count, days_back, result); 1375513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch request->ForwardResult(QueryMostVisitedURLsRequest::TupleType( 1376513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch request->handle(), *result)); 1377513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 1378513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1379513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid HistoryBackend::QueryMostVisitedURLsImpl(int result_count, 1380513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int days_back, 1381513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch MostVisitedURLList* result) { 1382513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!db_.get()) 1383513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 1384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedVector<PageUsageData> data; 1386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->QuerySegmentUsage(base::Time::Now() - 1387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta::FromDays(days_back), 1388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result_count, &data.get()); 1389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < data.size(); ++i) { 1391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageUsageData* current_data = data[i]; 1392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RedirectList redirects; 1393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetMostRecentRedirectsFrom(current_data->GetURL(), &redirects); 1394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MostVisitedURL url = MakeMostVisitedURL(*current_data, redirects); 1395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->push_back(url); 1396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::GetRedirectsFromSpecificVisit( 1400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitID cur_visit, history::RedirectList* redirects) { 1401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Follow any redirects from the given visit and add them to the list. 1402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It *should* be impossible to get a circular chain here, but we check 1403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // just in case to avoid infinite loops. 1404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL cur_url; 1405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<VisitID> visit_set; 1406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_set.insert(cur_visit); 1407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (db_->GetRedirectFromVisit(cur_visit, &cur_visit, &cur_url)) { 1408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visit_set.find(cur_visit) != visit_set.end()) { 1409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Loop in visit chain, giving up"; 1410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_set.insert(cur_visit); 1413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirects->push_back(cur_url); 1414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::GetRedirectsToSpecificVisit( 1418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitID cur_visit, 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectList* redirects) { 1420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Follow redirects going to cur_visit. These are added to |redirects| in 1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the order they are found. If a redirect chain looks like A -> B -> C and 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |cur_visit| = C, redirects will be {B, A} in that order. 1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL cur_url; 1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<VisitID> visit_set; 1428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_set.insert(cur_visit); 1429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (db_->GetRedirectToVisit(cur_visit, &cur_visit, &cur_url)) { 1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visit_set.find(cur_visit) != visit_set.end()) { 1431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Loop in visit chain, giving up"; 1432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visit_set.insert(cur_visit); 1435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirects->push_back(cur_url); 1436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::GetMostRecentRedirectsFrom( 1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& from_url, 1441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectList* redirects) { 1442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirects->clear(); 1443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 1444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID from_url_id = db_->GetRowForURL(from_url, NULL); 1447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitID cur_visit = db_->GetMostRecentVisitForURL(from_url_id, NULL); 1448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!cur_visit) 1449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // No visits for URL. 1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetRedirectsFromSpecificVisit(cur_visit, redirects); 1452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::GetMostRecentRedirectsTo( 1456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& to_url, 1457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectList* redirects) { 1458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirects->clear(); 1459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 1460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID to_url_id = db_->GetRowForURL(to_url, NULL); 1463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitID cur_visit = db_->GetMostRecentVisitForURL(to_url_id, NULL); 1464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!cur_visit) 1465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // No visits for URL. 1466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetRedirectsToSpecificVisit(cur_visit, redirects); 1468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::ScheduleAutocomplete(HistoryURLProvider* provider, 1472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HistoryURLProviderParams* params) { 1473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ExecuteWithDB should handle the NULL database case. 1474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch provider->ExecuteWithDB(this, db_.get(), params); 1475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::SetPageContents(const GURL& url, 1478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const string16& contents) { 1479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is histogrammed in the text database manager. 1480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!text_database_.get()) 1481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->AddPageContents(url, contents); 1483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::SetPageThumbnail( 1486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 1487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& thumbnail, 1488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ThumbnailScore& score) { 1489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get() || !thumbnail_db_.get()) 1490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow url_row; 1493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID url_id = db_->GetRowForURL(url, &url_row); 1494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url_id) { 1495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_->SetPageThumbnail(url, url_id, thumbnail, score, 1496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_row.last_visit()); 1497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 1500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::GetPageThumbnail( 1503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<GetPageThumbnailRequest> request, 1504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& page_url) { 1505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<RefCountedBytes> data; 1509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetPageThumbnailDirectly(page_url, &data); 1510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(GetPageThumbnailRequest::TupleType( 1512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->handle(), data)); 1513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::GetPageThumbnailDirectly( 1516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& page_url, 1517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<RefCountedBytes>* data) { 1518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (thumbnail_db_.get()) { 1519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *data = new RefCountedBytes; 1520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Time the result. 1522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks beginning_time = TimeTicks::Now(); 1523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectList redirects; 1525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID url_id; 1526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = false; 1527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If there are some redirects, try to get a thumbnail from the last 1529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // redirect destination. 1530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (GetMostRecentRedirectsFrom(page_url, &redirects) && 1531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !redirects.empty()) { 1532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((url_id = db_->GetRowForURL(redirects.back(), NULL))) 1533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = thumbnail_db_->GetPageThumbnail(url_id, &(*data)->data); 1534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we don't have a thumbnail from redirects, try the URL directly. 1537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!success) { 1538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((url_id = db_->GetRowForURL(page_url, NULL))) 1539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = thumbnail_db_->GetPageThumbnail(url_id, &(*data)->data); 1540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // In this rare case, we start to mine the older redirect sessions 1543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from the visit table to try to find a thumbnail. 1544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!success) { 1545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = GetThumbnailFromOlderRedirect(page_url, &(*data)->data); 1546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!success) 1549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *data = NULL; // This will tell the callback there was an error. 1550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_TIMES("History.GetPageThumbnail", 1552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks::Now() - beginning_time); 1553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1556513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid HistoryBackend::MigrateThumbnailsDatabase() { 1557513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // If there is no History DB, we can't record that the migration was done. 1558513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // It will be recorded on the next run. 1559513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (db_.get()) { 1560513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // If there is no thumbnail DB, we can still record a successful migration. 1561513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (thumbnail_db_.get()) { 1562513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch thumbnail_db_->RenameAndDropThumbnails(GetThumbnailFileName(), 1563513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GetFaviconsFileName()); 1564513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 1565513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch db_->ThumbnailMigrationDone(); 1566513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 1567513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 1568513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::GetThumbnailFromOlderRedirect( 1570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& page_url, 1571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<unsigned char>* data) { 1572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Look at a few previous visit sessions. 1573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector older_sessions; 1574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID page_url_id = db_->GetRowForURL(page_url, NULL); 1575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kVisitsToSearchForThumbnail = 4; 1576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetMostRecentVisitsForURL( 1577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch page_url_id, kVisitsToSearchForThumbnail, &older_sessions); 1578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Iterate across all those previous visits, and see if any of the 1580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // final destinations of those redirect chains have a good thumbnail 1581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for us. 1582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = false; 1583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (VisitVector::const_iterator it = older_sessions.begin(); 1584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !success && it != older_sessions.end(); ++it) { 1585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectList redirects; 1586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it->visit_id) { 1587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetRedirectsFromSpecificVisit(it->visit_id, &redirects); 1588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!redirects.empty()) { 1590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID url_id; 1591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((url_id = db_->GetRowForURL(redirects.back(), NULL))) 1592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = thumbnail_db_->GetPageThumbnail(url_id, data); 1593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return success; 1598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HistoryBackend::GetFavicon(scoped_refptr<GetFaviconRequest> request, 1601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& icon_url, 1602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int icon_types) { 1603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateFaviconMappingAndFetchImpl(NULL, icon_url, request, icon_types); 1604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1606ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HistoryBackend::UpdateFaviconMappingAndFetch( 1607ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<GetFaviconRequest> request, 1608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& page_url, 1609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& icon_url, 1610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IconType icon_type) { 1611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateFaviconMappingAndFetchImpl(&page_url, icon_url, request, icon_type); 1612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HistoryBackend::SetFaviconOutOfDateForPage(const GURL& page_url) { 1615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<IconMapping> icon_mappings; 1616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thumbnail_db_.get() || 1618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !thumbnail_db_->GetIconMappingsForPageURL(page_url, 1619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &icon_mappings)) 1620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 1623ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen m != icon_mappings.end(); ++m) { 1624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->SetFaviconLastUpdateTime(m->icon_id, Time()); 1625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 1627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::SetImportedFavicons( 1630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::vector<ImportedFaviconUsage>& favicon_usage) { 1631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get() || !thumbnail_db_.get()) 1632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time now = Time::Now(); 1635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Track all URLs that had their favicons set or updated. 1637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<GURL> favicons_changed; 1638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < favicon_usage.size(); i++) { 1640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL( 1641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon_usage[i].favicon_url, history::FAVICON, NULL); 1642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!favicon_id) { 1643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This favicon doesn't exist yet, so we create it using the given data. 1644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon_id = thumbnail_db_->AddFavicon(favicon_usage[i].favicon_url, 1645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen history::FAVICON); 1646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!favicon_id) 1647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; // Unable to add the favicon. 1648ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->SetFavicon(favicon_id, 1649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new RefCountedBytes(favicon_usage[i].png_data), now); 1650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Save the mapping from all the URLs to the favicon. 1653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkService* bookmark_service = GetBookmarkService(); 1654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::set<GURL>::const_iterator url = favicon_usage[i].urls.begin(); 1655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url != favicon_usage[i].urls.end(); ++url) { 1656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow url_row; 1657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->GetRowForURL(*url, &url_row)) { 1658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the URL is present as a bookmark, add the url in history to 1659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // save the favicon mapping. This will match with what history db does 1660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for regular bookmarked URLs with favicons - when history db is 1661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cleaned, we keep an entry in the db with 0 visits as long as that 1662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // url is bookmarked. 1663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bookmark_service && bookmark_service_->IsBookmarked(*url)) { 1664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow url_info(*url); 1665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_visit_count(0); 1666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_typed_count(0); 1667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_last_visit(base::Time()); 1668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_info.set_hidden(false); 1669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->AddURL(url_info); 1670ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->AddIconMapping(*url, favicon_id); 1671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicons_changed.insert(*url); 1672ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 1674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thumbnail_db_->GetIconMappingForPageURL(*url, FAVICON, NULL)) { 1675ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // URL is present in history, update the favicon *only* if it is not 1676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // set already. 1677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->AddIconMapping(*url, favicon_id); 1678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicons_changed.insert(*url); 1679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!favicons_changed.empty()) { 1685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Send the notification about the changed favicon URLs. 1686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconChangeDetails* changed_details = new FaviconChangeDetails; 1687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed_details->urls.swap(favicons_changed); 1688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastNotifications(NotificationType::FAVICON_CHANGED, changed_details); 1689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1692ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HistoryBackend::UpdateFaviconMappingAndFetchImpl( 1693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL* page_url, 1694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& icon_url, 1695ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<GetFaviconRequest> request, 1696ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int icon_types) { 1697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Check only a single type was given when the page_url was specified. 1698ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!page_url || (page_url && (icon_types == FAVICON || 1699ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen icon_types == TOUCH_ICON || icon_types == TOUCH_PRECOMPOSED_ICON))); 1700ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1704ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconData favicon; 1705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (thumbnail_db_.get()) { 1707ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const FaviconID favicon_id = 1708ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->GetFaviconIDForFaviconURL( 1709ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen icon_url, icon_types, &favicon.icon_type); 1710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (favicon_id) { 1711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<RefCountedBytes> data = new RefCountedBytes(); 1712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon.known_icon = true; 1713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time last_updated; 1714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (thumbnail_db_->GetFavicon(favicon_id, &last_updated, &data->data, 1715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL)) { 1716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon.expired = (Time::Now() - last_updated) > 1717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeDelta::FromDays(kFaviconRefetchDays); 1718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon.image_data = data; 1719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (page_url) 1722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetFaviconMapping(*page_url, favicon_id, favicon.icon_type); 1723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // else case, haven't cached entry yet. Caller is responsible for 1725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // downloading the favicon and invoking SetFavicon. 1726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen request->ForwardResult(GetFaviconRequest::TupleType( 1728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen request->handle(), favicon)); 1729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1731ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HistoryBackend::GetFaviconForURL( 1732ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<GetFaviconRequest> request, 1733ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& page_url, 1734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int icon_types) { 1735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1738ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconData favicon; 1739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get() && thumbnail_db_.get()) { 1741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Time the query. 1742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks beginning_time = TimeTicks::Now(); 1743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<IconMapping> icon_mappings; 1745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time last_updated; 1746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<RefCountedBytes> data = new RefCountedBytes(); 1747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings) && 1748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (icon_mappings.front().icon_type & icon_types) && 1749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->GetFavicon(icon_mappings.front().icon_id, &last_updated, 1750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &data->data, &favicon.icon_url)) { 1751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon.known_icon = true; 1752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon.expired = (Time::Now() - last_updated) > 1753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeDelta::FromDays(kFaviconRefetchDays); 1754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon.icon_type = icon_mappings.front().icon_type; 1755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon.image_data = data; 1756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UMA_HISTOGRAM_TIMES("History.GetFavIconForURL", // historical name 1759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks::Now() - beginning_time); 1760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult( 1763ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetFaviconRequest::TupleType(request->handle(), favicon)); 1764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1766ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HistoryBackend::SetFavicon( 1767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& page_url, 1768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& icon_url, 1769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<RefCountedMemory> data, 1770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IconType icon_type) { 1771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(data.get()); 1772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!thumbnail_db_.get() || !db_.get()) 1773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1775ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconID id = thumbnail_db_->GetFaviconIDForFaviconURL( 1776ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen icon_url, icon_type, NULL); 1777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!id) 1778ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen id = thumbnail_db_->AddFavicon(icon_url, icon_type); 1779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the image data. 1781ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->SetFavicon(id, data, Time::Now()); 1782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1783ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetFaviconMapping(page_url, id, icon_type); 1784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1786ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HistoryBackend::SetFaviconMapping(const GURL& page_url, 1787ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconID id, 1788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IconType icon_type) { 1789ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thumbnail_db_.get()) 1790ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 1791ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find all the pages whose favicons we should set, we want to set it for 1793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // all the pages in the redirect chain if it redirected. 1794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectList dummy_list; 1795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history::RedirectList* redirects; 1796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RedirectCache::iterator iter = recent_redirects_.Get(page_url); 1797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (iter != recent_redirects_.end()) { 1798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirects = &iter->second; 1799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This redirect chain should have the destination URL as the last item. 1801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!redirects->empty()); 1802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(redirects->back() == page_url); 1803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No redirect chain stored, make up one containing the URL we want to we 1805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // can use the same logic below. 1806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dummy_list.push_back(page_url); 1807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirects = &dummy_list; 1808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<GURL> favicons_changed; 1811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Save page <-> favicon association. 1813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (history::RedirectList::const_iterator i(redirects->begin()); 1814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != redirects->end(); ++i) { 1815ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconID replaced_id; 1816ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (AddOrUpdateIconMapping(*i, id, icon_type, &replaced_id)) { 1817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The page's favicon ID changed. This means that the one we just 1818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // changed from could have been orphaned, and we need to re-check it. 1819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is not super fast, but this case will get triggered rarely, 1820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // since normally a page will always map to the same favicon ID. It 1821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will mostly happen for favicons we import. 1822ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (replaced_id && !thumbnail_db_->HasMappingFor(replaced_id)) 1823ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->DeleteFavicon(replaced_id); 1824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1825ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicons_changed.insert(*i); 1826ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Send the notification about the changed favicons. 1830ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconChangeDetails* changed_details = new FaviconChangeDetails; 1831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changed_details->urls.swap(favicons_changed); 1832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastNotifications(NotificationType::FAVICON_CHANGED, changed_details); 1833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleCommit(); 1835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1837ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool HistoryBackend::AddOrUpdateIconMapping(const GURL& page_url, 1838ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconID id, 1839ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IconType icon_type, 1840ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconID* replaced_icon) { 1841ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *replaced_icon = 0; 1842ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<IconMapping> icon_mappings; 1843ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) { 1844ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // There is no mapping add it directly. 1845ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->AddIconMapping(page_url, id); 1846ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 1847ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1848ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Iterate all matched icon mappings, 1849ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // a. If the given icon id and matched icon id are same, return. 1850ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // b. If the given icon type and matched icon type are same, but icon id 1851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // are not, update the IconMapping. 1852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // c. If the given icon_type and matched icon type are not same, but 1853ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // either of them is ICON_TOUCH or ICON_PRECOMPOSED_TOUCH, update the 1854ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // IconMapping. 1855ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // d. Otherwise add a icon mapping. 1856ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 1857ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen m != icon_mappings.end(); ++m) { 1858ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (m->icon_id == id) 1859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The mapping is already there. 1860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 1861ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) || 1863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) || 1864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (icon_type == m->icon_type)) { 1865ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->UpdateIconMapping(m->mapping_id, id); 1866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *replaced_icon = m->icon_id; 1867ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 1868ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1869ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1870ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->AddIconMapping(page_url, id); 1871ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 1872ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1873ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::Commit() { 1875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 1876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that a commit may not actually have been scheduled if a caller 1879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // explicitly calls this instead of using ScheduleCommit. Likewise, we 1880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // may reset the flag written by a pending commit. But this is OK! It 1881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will merely cause extra commits (which is kind of the idea). We 1882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // could optimize more for this case (we may get two extra commits in 1883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // some cases) but it hasn't been important yet. 1884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CancelScheduledCommit(); 1885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->CommitTransaction(); 1887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; 1888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->BeginTransaction(); 1889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (thumbnail_db_.get()) { 1891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_->CommitTransaction(); 1892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(thumbnail_db_->transaction_nesting() == 0) << 1893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Somebody left a transaction open"; 1894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_->BeginTransaction(); 1895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (archived_db_.get()) { 1898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_->CommitTransaction(); 1899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_->BeginTransaction(); 1900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_database_.get()) { 1903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->CommitTransaction(); 1904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->BeginTransaction(); 1905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::ScheduleCommit() { 1909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (scheduled_commit_.get()) 1910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scheduled_commit_ = new CommitLaterTask(this); 1912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 1913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(scheduled_commit_.get(), 1914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &CommitLaterTask::RunCommit), 1915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCommitIntervalMs); 1916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::CancelScheduledCommit() { 1919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (scheduled_commit_) { 1920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scheduled_commit_->Cancel(); 1921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scheduled_commit_ = NULL; 1922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::ProcessDBTaskImpl() { 1926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) { 1927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // db went away, release all the refs. 1928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReleaseDBTasks(); 1929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove any canceled tasks. 1933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (!db_task_requests_.empty() && db_task_requests_.front()->canceled()) { 1934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_task_requests_.front()->Release(); 1935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_task_requests_.pop_front(); 1936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_task_requests_.empty()) 1938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Run the first task. 1941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HistoryDBTaskRequest* request = db_task_requests_.front(); 1942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_task_requests_.pop_front(); 1943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->value->RunOnDBThread(this, db_.get())) { 1944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The task is done. Notify the callback. 1945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(HistoryDBTaskRequest::TupleType()); 1946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We AddRef'd the request before adding, need to release it now. 1947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->Release(); 1948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tasks wants to run some more. Schedule it at the end of current tasks. 1950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_task_requests_.push_back(request); 1951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // And process it after an invoke later. 1952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 1953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &HistoryBackend::ProcessDBTaskImpl)); 1954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::ReleaseDBTasks() { 1958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::list<HistoryDBTaskRequest*>::iterator i = 1959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_task_requests_.begin(); i != db_task_requests_.end(); ++i) { 1960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*i)->Release(); 1961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_task_requests_.clear(); 1963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 1966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 1967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Generic operations 1968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 1969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 1970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { 1972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<GURL>::const_iterator url = urls.begin(); url != urls.end(); 1973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++url) { 1974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expirer_.DeleteURL(*url); 1975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetStartDate(&first_recorded_time_); 1978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Force a commit, if the user is deleting something for privacy reasons, we 1979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // want to get it on disk ASAP. 1980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Commit(); 1981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::DeleteURL(const GURL& url) { 1984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expirer_.DeleteURL(url); 1985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetStartDate(&first_recorded_time_); 1987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Force a commit, if the user is deleting something for privacy reasons, we 1988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // want to get it on disk ASAP. 1989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Commit(); 1990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::ExpireHistoryBetween( 1993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<ExpireHistoryRequest> request, 1994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::set<GURL>& restrict_urls, 1995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time begin_time, 1996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Time end_time) { 1997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 1998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_.get()) { 2001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (begin_time.is_null() && end_time.is_null() && restrict_urls.empty()) { 2002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Special case deleting all history so it can be faster and to reduce the 2003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // possibility of an information leak. 2004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DeleteAllHistory(); 2005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 2006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clearing parts of history, have the expirer do the depend 2007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expirer_.ExpireHistoryBetween(restrict_urls, begin_time, end_time); 2008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Force a commit, if the user is deleting something for privacy reasons, 2010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we want to get it on disk ASAP. 2011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Commit(); 2012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (begin_time <= first_recorded_time_) 2016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetStartDate(&first_recorded_time_); 2017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->ForwardResult(ExpireHistoryRequest::TupleType()); 2019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (history_publisher_.get() && restrict_urls.empty()) 2021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch history_publisher_->DeleteUserHistoryBetween(begin_time, end_time); 2022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) { 2025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_.get()) 2026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { 2029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow url_row; 2030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->GetRowForURL(*i, &url_row)) 2031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; // The URL isn't in the db; nothing to do. 2032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VisitVector visits; 2034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetVisitsForURL(url_row.id(), &visits); 2035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visits.empty()) 2037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expirer_.DeleteURL(*i); // There are no more visits; nuke the URL. 2038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::ProcessDBTask( 2042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<HistoryDBTaskRequest> request) { 2043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(request.get()); 2044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request->canceled()) 2045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool task_scheduled = !db_task_requests_.empty(); 2048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure we up the refcount of the request. ProcessDBTaskImpl will 2049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // release when done with the task. 2050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->AddRef(); 2051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_task_requests_.push_back(request.get()); 2052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!task_scheduled) { 2053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No other tasks are scheduled. Process request now. 2054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessDBTaskImpl(); 2055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::BroadcastNotifications( 2059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType type, 2060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HistoryDetails* details_deleted) { 2061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(delegate_.get()); 2062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate_->BroadcastNotifications(type, details_deleted); 2063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Deleting -------------------------------------------------------------------- 2066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryBackend::DeleteAllHistory() { 2068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Our approach to deleting all history is: 2069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1. Copy the bookmarks and their dependencies to new tables with temporary 2070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // names. 2071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2. Delete the original tables. Since tables can not share pages, we know 2072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that any data we don't want to keep is now in an unused page. 2073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 3. Renaming the temporary tables to match the original. 2074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 4. Vacuuming the database to delete the unused pages. 2075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Since we are likely to have very few bookmarks and their dependencies 2077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // compared to all history, this is also much faster than just deleting from 2078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the original tables directly. 2079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get the bookmarked URLs. 2081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<GURL> starred_urls; 2082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkService* bookmark_service = GetBookmarkService(); 2083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bookmark_service) 2084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_service_->GetBookmarks(&starred_urls); 2085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<URLRow> kept_urls; 2087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < starred_urls.size(); i++) { 2088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRow row; 2089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->GetRowForURL(starred_urls[i], &row)) 2090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 2091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clear the last visit time so when we write these rows they are "clean." 2093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch row.set_last_visit(Time()); 2094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch row.set_visit_count(0); 2095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch row.set_typed_count(0); 2096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kept_urls.push_back(row); 2097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clear thumbnail and favicon history. The favicons for the given URLs will 2100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be kept. 2101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ClearAllThumbnailHistory(&kept_urls)) { 2102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Thumbnail history could not be cleared"; 2103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We continue in this error case. If the user wants to delete their 2104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // history, we should delete as much as we can. 2105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ClearAllMainHistory will change the IDs of the URLs in kept_urls. Therfore, 2108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we clear the list afterwards to make sure nobody uses this invalid data. 2109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ClearAllMainHistory(kept_urls)) 2110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Main history could not be cleared"; 2111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kept_urls.clear(); 2112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete FTS files & archived history. 2114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_database_.get()) { 2115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We assume that the text database has one transaction on them that we need 2116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to close & restart (the long-running history transaction). 2117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->CommitTransaction(); 2118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->DeleteAll(); 2119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_database_->BeginTransaction(); 2120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (archived_db_.get()) { 2123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Close the database and delete the file. 2124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_.reset(); 2125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath archived_file_name = GetArchivedFileName(); 2126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_util::Delete(archived_file_name, false); 2127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now re-initialize the database (which may fail). 2129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_.reset(new ArchivedDatabase()); 2130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!archived_db_->Init(archived_file_name)) { 2131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "Could not initialize the archived database."; 2132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_.reset(); 2133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 2134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Open our long-running transaction on this database. 2135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch archived_db_->BeginTransaction(); 2136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetStartDate(&first_recorded_time_); 2140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Send out the notfication that history is cleared. The in-memory datdabase 2142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will pick this up and clear itself. 2143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLsDeletedDetails* details = new URLsDeletedDetails; 2144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch details->all_history = true; 2145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BroadcastNotifications(NotificationType::HISTORY_URLS_DELETED, details); 2146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::ClearAllThumbnailHistory( 2149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<URLRow>* kept_urls) { 2150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!thumbnail_db_.get()) { 2151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we have no reference to the thumbnail database, maybe there was an 2152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // error opening it. In this case, we just try to blow it away to try to 2153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // fix the error if it exists. This may fail, in which case either the 2154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // file doesn't exist or there's no more we can do. 2155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_util::Delete(GetThumbnailFileName(), false); 2156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 2157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create the duplicate favicon table, this is where the favicons we want 2160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to keep will be stored. 2161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thumbnail_db_->InitTemporaryFaviconsTable()) 2162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 2163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thumbnail_db_->InitTemporaryIconMappingTable()) 2165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This maps existing favicon IDs to the ones in the temporary table. 2168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen typedef std::map<FaviconID, FaviconID> FaviconMap; 2169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconMap copied_favicons; 2170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Copy all unique favicons to the temporary table, and update all the 2172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // URLs to have the new IDs. 2173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<URLRow>::iterator i = kept_urls->begin(); 2174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != kept_urls->end(); ++i) { 2175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<IconMapping> icon_mappings; 2176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!thumbnail_db_->GetIconMappingsForPageURL(i->url(), &icon_mappings)) 2177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 2178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 2180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen m != icon_mappings.end(); ++m) { 2181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconID old_id = m->icon_id; 2182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconID new_id; 2183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconMap::const_iterator found = copied_favicons.find(old_id); 2184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (found == copied_favicons.end()) { 2185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_id = thumbnail_db_->CopyToTemporaryFaviconTable(old_id); 2186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen copied_favicons[old_id] = new_id; 2187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 2188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We already encountered a URL that used this favicon, use the ID we 2189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // previously got. 2190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_id = found->second; 2191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Add Icon mapping, and we don't care wheteher it suceeded or not. 2193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->AddToTemporaryIconMappingTable(i->url(), new_id); 2194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Rename the duplicate favicon and icon_mapping back table and recreate the 2198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // other tables. This will make the database consistent again. 2199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->CommitTemporaryFaviconTable(); 2200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen thumbnail_db_->CommitTemporaryIconMappingTable(); 2201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_->RecreateThumbnailTable(); 2203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Vacuum to remove all the pages associated with the dropped tables. There 2205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // must be no transaction open on the table when we do this. We assume that 2206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // our long-running transaction is open, so we complete it and start it again. 2207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(thumbnail_db_->transaction_nesting() == 1); 2208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_->CommitTransaction(); 2209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_->Vacuum(); 2210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thumbnail_db_->BeginTransaction(); 2211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 2212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryBackend::ClearAllMainHistory( 2215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<URLRow>& kept_urls) { 2216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create the duplicate URL table. We will copy the kept URLs into this. 2217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->CreateTemporaryURLTable()) 2218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Insert the URLs into the temporary table, we need to keep a map of changed 2221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IDs since the ID will be different in the new table. 2222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef std::map<URLID, URLID> URLIDMap; 2223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLIDMap old_to_new; // Maps original ID to new one. 2224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<URLRow>::const_iterator i = kept_urls.begin(); 2225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != kept_urls.end(); 2226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++i) { 2227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLID new_id = db_->AddTemporaryURL(*i); 2228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_to_new[i->id()] = new_id; 2229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Replace the original URL table with the temporary one. 2232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!db_->CommitTemporaryURLTable()) 2233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete the old tables and recreate them empty. 2236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->RecreateAllTablesButURL(); 2237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Vacuum to reclaim the space from the dropped tables. This must be done 2239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when there is no transaction open, and we assume that our long-running 2240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // transaction is currently open. 2241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->CommitTransaction(); 2242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->Vacuum(); 2243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->BeginTransaction(); 2244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_->GetStartDate(&first_recorded_time_); 2245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 2247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2249c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBookmarkService* HistoryBackend::GetBookmarkService() { 2250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bookmark_service_) 2251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_service_->BlockTillLoaded(); 2252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bookmark_service_; 2253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace history 2256