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