history_backend.cc revision bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_backend.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <functional> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 17bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/files/file_enumerator.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h" 209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/rand_util.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/history_url_provider.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_service.h" 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/favicon/favicon_changed_details.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/download_row.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_db_task.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_notifications.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_publisher.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/in_memory_history_backend.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/page_usage_data.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/select_favicon_frames.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/top_sites.h" 38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/history/typed_url_syncable_service.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/visit_filter.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/importer/imported_favicon_usage.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/error_delegate_util.h" 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/android/android_provider_backend.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The HistoryBackend consists of a number of components: 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase (stores past 3 months of history) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase (stores a list of URLs) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadDatabase (stores a list of downloads) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase (stores a list of visits for the URLs) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSegmentDatabase (stores groups of URLs for the most visited view). 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ArchivedDatabase (stores history older than 3 months) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase (stores a list of URLs) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadDatabase (stores a list of downloads) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase (stores a list of visits for the URLs) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (this does not store visit segments as they expire after 3 mos.) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpireHistoryBackend (manages moving things from HistoryDatabase to 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) the ArchivedDatabase and deleting) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we keep segment data for in days. Currently 3 months. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This value needs to be greater or equal to 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dependency between MostVisitedModel and the history backend. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSegmentDataRetention = 90; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we'll wait to do a commit, so that things are batched together. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCommitIntervalSeconds = 10; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of time before we re-fetch the favicon. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kFaviconRefetchDays = 7; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetSessionTabs returns all open tabs, or tabs closed kSessionCloseTimeWindow 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// seconds ago. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSessionCloseTimeWindowSecs = 10; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum number of items we'll allow in the redirect list before 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deleting some. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxRedirectCount = 32; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The number of days old a history entry can be before it is considered "old" 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and is archived. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kArchiveDaysThreshold = 90; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The maximum number of top sites to track when recording top page visit stats. 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic const size_t kPageVisitStatsMaxTopSites = 50; 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts from PageUsageData to MostVisitedURL. |redirects| is a 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list of redirects for this URL. Empty list means no redirects. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RedirectList& redirects) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL mv; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.url = page_data.GetURL(); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.title = page_data.GetTitle(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirects.empty()) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirects must contain at least the target url. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects = redirects; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mv.redirects[mv.redirects.size() - 1] != mv.url) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last url must be the target url. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mv; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This task is run on a timer so that commits happen at regular intervals 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so they are batched together. The important thing about this class is that 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it supports canceling of the task so the reference to the backend will be 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// freed. The problem is that when history is shutting down, there is likely 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be one of these commits still pending and holding a reference. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The backend can call Cancel to have this task release the reference. The 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// task will still run (if we ever get to processing the event before 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shutdown), but it will not do anything. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that this is a refcounted object and is not a task in itself. It should 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be assigned to a RunnableMethod. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(brettw): bug 1165182: This should be replaced with a 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::WeakPtrFactory which will handle everything automatically (like we do 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in ExpireHistoryBackend). 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CommitLaterTask : public base::RefCounted<CommitLaterTask> { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CommitLaterTask(HistoryBackend* history_backend) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : history_backend_(history_backend) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The backend will call this function if it is being destroyed so that we 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release our reference. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Cancel() { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_ = NULL; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunCommit() { 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (history_backend_.get()) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_->Commit(); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCounted<CommitLaterTask>; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~CommitLaterTask() {} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryBackend> history_backend_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HistoryBackend -------------------------------------------------------------- 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistoryBackend::HistoryBackend(const base::FilePath& history_dir, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(delegate), 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_(id), 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_dir_(history_dir), 1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_(false), 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expirer_(this, bookmark_service), 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recent_redirects_(kMaxRedirectCount), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_(NULL), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_(false), 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_(bookmark_service) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryBackend::~HistoryBackend() { 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!scheduled_commit_.get()) << "Deleting without cleanup"; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseDBTasks(); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First close the databases before optionally running the "destroy" task. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!backend_destroy_task_.is_null()) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify an interested party (typically a unit test) that we're done. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(backend_destroy_message_loop_); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_->PostTask(FROM_HERE, backend_destroy_task_); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetAndroidCacheFileName()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Init(const std::string& languages, bool force_fail) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!force_fail) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitImpl(languages); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->DBLoaded(id_); 212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_.reset(new TypedUrlSyncableService(this)); 213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch memory_pressure_listener_.reset(new base::MemoryPressureListener( 214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&HistoryBackend::OnMemoryPressure, base::Unretained(this)))); 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PopulateMostVisitedURLMap(); 217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryBackend::SetOnBackendDestroyTask(base::MessageLoop* message_loop, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& task) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!backend_destroy_task_.is_null()) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Setting more than one destroy task, overriding"; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_ = message_loop; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_task_ = task; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Closing() { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Any scheduled commit will have a reference to us, we must make it 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release that reference before we can be destroyed. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release our reference to the delegate, this reference will be keeping the 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history service alive. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_.reset(); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::NotifyRenderProcessHostDestruction(const void* host) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker_.NotifyRenderProcessHostDestruction(host); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetThumbnailFileName() const { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kThumbnailsFilename); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetFaviconsFileName() const { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kFaviconsFilename); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetArchivedFileName() const { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kArchivedHistoryFilename); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetAndroidCacheFileName() const { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kAndroidCacheFilename); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SegmentID HistoryBackend::GetLastSegmentID(VisitID from_visit) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set is used to detect referrer loops. Should not happen, but can 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the database is corrupt. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = from_visit; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (visit_id) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow row; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForVisit(visit_id, &row)) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row.segment_id) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row.segment_id; // Found a visit in this change with a segment. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the referrer of this visit, if any. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_id = row.referring_visit; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(visit_id) != visit_set.end()) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in referer chain, giving up"; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(visit_id); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SegmentID HistoryBackend::UpdateSegments( 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID from_visit, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition_type, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Time ts) { 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only consider main frames. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!content::PageTransitionIsMainFrame(transition_type)) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SegmentID segment_id = 0; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(transition_type); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Are we at the beginning of a new segment? 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that navigating to an existing entry (with back/forward) reuses the 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same transition type. We are not adding it as a new segment in that case 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because if this was the target of a redirect, we might end up with 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2 entries for the same final URL. Ex: User types google.net, gets 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirected to google.com. A segment is created for google.net. On 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // google.com users navigates through a link, then press back. That last 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation is for the entry google.com transition typed. We end up adding 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a segment for that one as well. So we end up with google.net and google.com 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the segement table, showing as 2 entries in the NTP. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note also that we should still be updating the visit count for that segment 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which we are not doing now. It should be addressed when 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/96860 is fixed. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((t == content::PAGE_TRANSITION_TYPED || 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t == content::PAGE_TRANSITION_AUTO_BOOKMARK) && 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (transition_type & content::PAGE_TRANSITION_FORWARD_BACK) == 0) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If so, create or get the segment. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string segment_name = db_->ComputeSegmentName(url); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(segment_id = db_->GetSegmentNamed(segment_name))) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(segment_id = db_->CreateSegment(url_id, segment_name))) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: if we update an existing segment, we update the url used to 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // represent that segment in order to minimize stale most visited 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // images. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateSegmentRepresentationURL(segment_id, url_id); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: it is possible there is no segment ID set for this visit chain. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This can happen if the initial navigation wasn't AUTO_BOOKMARK or 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TYPED. (For example GENERATED). In this case this visit doesn't count 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // toward any segment. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(segment_id = GetLastSegmentID(from_visit))) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the segment in the visit. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->SetSegmentID(visit_id, segment_id)) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally, increase the counter for that segment / day. 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->IncreaseSegmentVisitCount(segment_id, ts, 1)) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return segment_id; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateWithPageEndTime(const void* host, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 page_id, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_ts) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be filled with the URL ID and the visit ID of the last addition. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = tracker_.GetLastVisit(host, page_id, url); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(visit_id, end_ts); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateVisitDuration(VisitID visit_id, const Time end_ts) { 367b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the starting visit_time for visit_id. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_row; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetRowForVisit(visit_id, &visit_row)) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should never have a negative duration time even when time is skewed. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.visit_duration = end_ts > visit_row.visit_time ? 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_ts - visit_row.visit_time : TimeDelta::FromMicroseconds(0); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateVisitRow(visit_row); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPage(const HistoryAddPageArgs& request) { 381b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be filled with the URL ID and the visit ID of the last addition. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<URLID, VisitID> last_ids(0, tracker_.GetLastVisit( 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.id_scope, request.page_id, request.referrer)); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID from_visit_id = last_ids.second; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a redirect chain is given, we expect the last item in that chain to be 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the final URL. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request.redirects.empty() || 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects.back() == request.url); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is adding older history, we need to make sure our times 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are correct. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.time < first_recorded_time_) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = request.time; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition request_transition = request.transition; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition stripped_transition = 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(request_transition); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_keyword_generated = 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition == content::PAGE_TRANSITION_KEYWORD_GENERATED); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is navigating to a not-previously-typed intranet hostname, 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change the transition to TYPED so that the omnibox will learn that this is 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a known host. 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_redirects = request.redirects.size() > 1; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionIsMainFrame(request_transition) && 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition != content::PAGE_TRANSITION_TYPED) && 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_keyword_generated) { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& origin_url(has_redirects ? 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects[0] : request.url); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (origin_url.SchemeIs(chrome::kHttpScheme) || 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origin_url.SchemeIs(chrome::kHttpsScheme) || 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origin_url.SchemeIs(chrome::kFtpScheme)) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host(origin_url.host()); 419a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) size_t registry_length = 420a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::GetRegistryLength( 421a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) host, 422a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, 423a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); 424a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (registry_length == 0 && !db_->IsTypedHost(host)) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition = content::PAGE_TRANSITION_TYPED; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition = 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition | 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionGetQualifier(request_transition)); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_redirects) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The single entry is both a chain start and end. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = content::PageTransitionFromInt( 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition | 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect case (one element means just the page itself). 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids = AddPageVisit(request.url, request.time, 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids.second, t, request.visit_source); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the segment for this visit. KEYWORD_GENERATED visits should not 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // result in changing most visited, so we don't update segments (most 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visited db). 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_keyword_generated) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateSegments(request.url, from_visit_id, last_ids.second, t, 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.time); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the referrer's duration. 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(from_visit_id, request.time); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirect case. Add the redirect chain. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition redirect_info = 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects = request.redirects; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirects[0].SchemeIs(chrome::kAboutScheme)) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the redirect source + referrer is "about" we skip it. This 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happens when a page opens a new frame/window to about:blank and then 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // script sets the URL to somewhere else (used to hide the referrer). It 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // would be nice to keep all these redirects properly but we don't ever 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // see the initial about:blank load, so we don't know where the 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subsequent client redirect came from. 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this case, we just don't bother hooking up the source of the 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirects, so we remove it. 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects.erase(redirects.begin()); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (request_transition & content::PAGE_TRANSITION_CLIENT_REDIRECT) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_info = content::PAGE_TRANSITION_CLIENT_REDIRECT; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The first entry in the redirect chain initiated a client redirect. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't add this to the database since the referrer is already 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there, so we skip over it but change the transition type of the first 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transition to client redirect. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The referrer is invalid when restoring a session that features an 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // https tab that redirects to a different host or to http. In this 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case we don't need to reconnect the new redirect with the existing 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chain. 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.referrer.is_valid()) { 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request.referrer == redirects[0]); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects.erase(redirects.begin()); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the navigation entry for this visit has replaced that for the 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first visit, remove the CHAIN_END marker from the first visit. This 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can be called a lot, for example, the page cycler, and most of the 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time we won't have changed anything. 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_row; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.did_replace_entry && 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetRowForVisit(last_ids.second, &visit_row) && 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition & content::PAGE_TRANSITION_CHAIN_END) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition = content::PageTransitionFromInt( 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition & ~content::PAGE_TRANSITION_CHAIN_END); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateVisitRow(visit_row); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t redirect_index = 0; redirect_index < redirects.size(); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_index++) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt(stripped_transition | redirect_info); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is the last transition, add a CHAIN_END marker 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirect_index == (redirects.size() - 1)) { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t = content::PageTransitionFromInt( 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t | content::PAGE_TRANSITION_CHAIN_END); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record all redirect visits with the same timestamp. We don't display 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them anyway, and if we ever decide to, we can reconstruct their order 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the redirect chain. 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids = AddPageVisit(redirects[redirect_index], 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.time, last_ids.second, 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t, request.visit_source); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (t & content::PAGE_TRANSITION_CHAIN_START) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the segment for this visit. 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateSegments(redirects[redirect_index], 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_visit_id, last_ids.second, t, request.time); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the visit_details for this visit. 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(from_visit_id, request.time); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subsequent transitions in the redirect list must all be server 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirects. 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_info = content::PAGE_TRANSITION_SERVER_REDIRECT; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Last, save this redirect chain for later so we can set titles & favicons 535bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // on the redirected pages properly. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recent_redirects_.Put(request.url, redirects); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the last visit to the tracker so we can get outgoing transitions. 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(evanm): Due to http://b/1194536 we lose the referrers of a subframe 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation anyway, so last_visit_id is always zero for them. But adding 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them here confuses main frame history, so we skip them for now. 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stripped_transition != content::PAGE_TRANSITION_AUTO_SUBFRAME && 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition != content::PAGE_TRANSITION_MANUAL_SUBFRAME && 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_keyword_generated) { 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker_.AddVisit(request.id_scope, request.page_id, request.url, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids.second); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::InitImpl(const std::string& languages) { 557b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!db_) << "Initializing HistoryBackend twice"; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the rare case where the db fails to initialize a dialog may get shown 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the blocks the caller, yet allows other messages through. For this reason 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we only set db_ to the created database if creation is successful. That 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // way other methods won't do anything as db_ is still NULL. 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Compute the file names. 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath history_name = history_dir_.Append(chrome::kHistoryFilename); 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath thumbnail_name = GetThumbnailFileName(); 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath archived_name = GetArchivedFileName(); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 570bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Delete the old index database files which are no longer used. 571bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch DeleteFTSIndexDatabases(); 572bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // History database. 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(new HistoryDatabase()); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Unretained to avoid a ref loop with db_. 5777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) db_->set_error_callback( 5787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::DatabaseErrorCallback, 5797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Unretained(this))); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sql::InitStatus status = db_->Init(history_name); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case sql::INIT_OK: 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case sql::INIT_FAILURE: { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A NULL db_ will cause all calls on this object to notice this error 5877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // and to not continue. If the error callback scheduled killing the 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database, the task it posted has not executed yet. Try killing the 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database now before we close it. 5907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool kill_db = scheduled_kill_db_; 5917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (kill_db) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KillHistoryDatabase(); 5937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.AttemptedToFixProfileError", kill_db); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->NotifyProfileError(id_, status); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill the in-memory database and send it back to the history service on the 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main thread. 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InMemoryHistoryBackend* mem_backend = new InMemoryHistoryBackend; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mem_backend->Init(history_name, db_.get())) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->SetInMemoryBackend(id_, mem_backend); // Takes ownership of 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pointer. 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete mem_backend; // Error case, run without the in-memory DB. 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginExclusiveMode(); // Must be after the mem backend read the data. 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 612bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Create the history publisher which needs to be passed on to the thumbnail 613bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // database for publishing history. 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_publisher_.reset(new HistoryPublisher()); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!history_publisher_->Init()) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The init may fail when there are no indexers wanting our history. 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hence no need to log the failure. 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_publisher_.reset(); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Thumbnail database. 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(new ThumbnailDatabase()); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetNeedsThumbnailMigration()) { 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No convertion needed - use new filename right away. 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_name = GetFaviconsFileName(); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thumbnail_db_->Init(thumbnail_name, 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_publisher_.get(), 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.get()) != sql::INIT_OK) { 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unlike the main database, we don't error out when the database is too 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new because this error is much less severe. Generally, this shouldn't 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happen since the thumbnail and main datbase versions should be in sync. 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'll just continue without thumbnails & favicons in this case or any 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other error. 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the thumbnail database."; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetNeedsThumbnailMigration()) { 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Starting TopSites migration"; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->StartTopSitesMigration(id_); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Archived database. 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->needs_version_17_migration()) { 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See needs_version_17_migration() decl for more. In this case, we want 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to delete the archived database and need to do so before we try to 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // open the file. We can ignore any error (maybe the file doesn't exist). 649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(archived_name); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(new ArchivedDatabase()); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!archived_db_->Init(archived_name)) { 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the archived database."; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Generate the history and thumbnail database metrics only after performing 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any migration work. 6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::RandInt(1, 100) == 50) { 6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Only do this computation sometimes since it can be expensive. 6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->ComputeDatabaseMetrics(history_name); 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->ComputeDatabaseMetrics(); 6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tell the expiration module about all the nice databases we made. This must 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happen before db_->Init() is called since the callback ForceArchiveHistory 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may need to expire stuff. 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // *sigh*, this can all be cleaned up when that migration code is removed. 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The main DB initialization should intuitively be first (not that it 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually matters) and the expirer should be set last. 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.SetDatabases(db_.get(), archived_db_.get(), 673bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch thumbnail_db_.get()); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open the long-running transaction. 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 677b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 679b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the first item in our database. 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start expiring old stuff. 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.StartArchivingOldStuff(TimeDelta::FromDays(kArchiveDaysThreshold)); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 689b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(new AndroidProviderBackend( 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAndroidCacheFileName(), db_.get(), thumbnail_db_.get(), 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_, delegate_.get())); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HISTOGRAM_TIMES("History.InitTime", 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 700ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid HistoryBackend::OnMemoryPressure( 701ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 702ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool trim_aggressively = memory_pressure_level == 703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL; 704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (db_) 705ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db_->TrimMemory(trim_aggressively); 706ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (thumbnail_db_) 707ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch thumbnail_db_->TrimMemory(trim_aggressively); 708ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (archived_db_) 709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch archived_db_->TrimMemory(trim_aggressively); 710ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloseAllDatabases() { 713b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Commit the long-running transaction. 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 718b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 722b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->CommitTransaction(); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::pair<URLID, VisitID> HistoryBackend::AddPageVisit( 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time time, 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID referring_visit, 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition, 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Top-level frame navigations are visible, everything else is hidden 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool new_hidden = !content::PageTransitionIsMainFrame(transition); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: This code must stay in sync with 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExpireHistoryBackend::ExpireURLsForVisits(). 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkasting): http://b/1148304 We shouldn't be marking so many URLs as 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typed, which would eliminate the need for this code. 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int typed_increment = 0; 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition_type = 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(transition); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((transition_type == content::PAGE_TRANSITION_TYPED && 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !content::PageTransitionIsRedirect(transition)) || 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition_type == content::PAGE_TRANSITION_KEYWORD_GENERATED) 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typed_increment = 1; 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Only count the page visit if it came from user browsing and only count it 751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // once when cycling through a redirect chain. 752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (visit_source == SOURCE_BROWSED && 753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (transition & content::PAGE_TRANSITION_CHAIN_END) != 0) { 754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RecordTopPageVisitStats(url); 755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if this URL is already in the DB. 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update of an existing row. 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionStripQualifier(transition) != 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_RELOAD) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(url_info.visit_count() + 1); 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typed_increment) 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(url_info.typed_count() + typed_increment); 768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (url_info.last_visit() < time) 769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_info.set_last_visit(time); 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only allow un-hiding of pages, never hiding. 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_hidden) 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(url_id, url_info); 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Addition of a new row. 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(1); 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(typed_increment); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(time); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(new_hidden); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_id = db_->AddURL(url_info); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding URL failed."; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(0, 0); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.id_ = url_id; 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the visit with the time to the database. 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, time, referring_visit, transition, 0); 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = db_->AddVisit(&visit_info, visit_source); 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification of the visit. 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_id) { 801b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 802b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlVisited(transition, &url_info); 803b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLVisitedDetails* details = new URLVisitedDetails; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->transition = transition; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->row = url_info; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(meelapshah) Disabled due to potential PageCycler regression. 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-enable this. 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetMostRecentRedirectsTo(url, &details->redirects); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URL_VISITED, details); 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to build visit insert statement: " 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "url_id = " << url_id; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(url_id, visit_id); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPagesWithDetails(const URLRows& urls, 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 821b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> modified(new URLsModifiedDetails); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = urls.begin(); i != urls.end(); ++i) { 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!i->last_visit().is_null()); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will add to either the archived database or the main one depending on 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the date of the added visit. 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase* url_database; 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase* visit_database; 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsExpiredVisitTime(i->last_visit())) { 833b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!archived_db_) 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // No archived database to save it to, just forget this. 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_database = archived_db_.get(); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_database = archived_db_.get(); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_database = db_.get(); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_database = db_.get(); 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow existing_url; 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = url_database->GetRowForURL(i->url(), &existing_url); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the page if it doesn't exist. 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_id = url_database->AddURL(*i); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Could not add row to DB"; 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->typed_count() > 0) { 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modified->changed_urls.push_back(*i); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modified->changed_urls.back().set_id(url_id); // *i likely has |id_| 0. 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sync code manages the visits itself. 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_source != SOURCE_SYNCED) { 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make up a visit to correspond to the last visit to the page. 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, i->last_visit(), 0, 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_LINK | 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END), 0); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!visit_database->AddVisit(&visit_info, visit_source)) { 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding visit failed."; 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 877b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 878b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&modified->changed_urls); 879b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification for typed URLs that have been modified. This 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be picked up by the in-memory URL database on the main thread. 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modified.release()); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) { 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return time < expirer_.GetCurrentArchiveTime(); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetPageTitle(const GURL& url, 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title) { 897b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search for recent redirects which should get the same title. We make a 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dummy list containing the exact URL visited if there are no redirects so 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the processing below can be the same. 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList dummy_list; 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects; 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(url); 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &iter->second; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This redirect chain should have the destination URL as the last item. 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirects->empty()); 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirects->back() == url); 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect chain stored, make up one containing the URL we want so we 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can use the same logic below. 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dummy_list.push_back(url); 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &dummy_list; 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> details(new URLsModifiedDetails); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirects->size(); i++) { 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID row_id = db_->GetRowForURL(redirects->at(i), &row); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row_id && row.title() != title) { 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_title(title); 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(row_id, row); 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->changed_urls.push_back(row); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast notifications for any URLs that have changed. This will 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the in-memory database and the InMemoryURLIndex. 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!details->changed_urls.empty()) { 933b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 934b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&details->changed_urls); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details.release()); 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPageNoVisitForBookmark(const GURL& url, 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title) { 943b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is already known, nothing to do. 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!title.empty()) { 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_title(title); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_title(UTF8ToUTF16(url.spec())); 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(Time::Now()); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the page hidden. If the user types it in, it'll unhide. 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(true); 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::IterateURLs( 96790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const scoped_refptr<visitedlink::VisitedLinkDelegate::URLEnumerator>& 9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator) { 969b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase::URLEnumerator e; 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->InitURLEnumeratorForEverything(&e)) { 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (e.GetNextURL(&info)) { 9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator->OnURL(info.url()); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(true); // Success. 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(false); // Failure. 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetAllTypedURLs(URLRows* urls) { 984b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetAllTypedUrls(urls); 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsForURL(URLID id, VisitVector* visits) { 990b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetVisitsForURL(id, visits); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentVisitsForURL(URLID id, 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits, 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 998b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetMostRecentVisitsForURL(id, max_visits, visits); 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::UpdateURL(URLID id, const history::URLRow& url) { 1004b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->UpdateURLRow(id, url); 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::AddVisits(const GURL& url, 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<VisitInfo>& visits, 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 1012b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<VisitInfo>::const_iterator visit = visits.begin(); 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit != visits.end(); ++visit) { 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddPageVisit( 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, visit->first, 0, visit->second, visit_source).first) { 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::RemoveVisits(const VisitVector& visits) { 1027b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.ExpireVisits(visits); 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsSource(const VisitVector& visits, 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSourceMap* sources) { 1037b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsSource(visits, sources); 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetURL(const GURL& url, history::URLRow* url_row) { 1045b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetRowForURL(url, url_row) != 0; 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryURL(scoped_refptr<QueryURLRequest> request, 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool want_visits) { 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow* row = &request->value.a; 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits = &request->value.b; 1059b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetRowForURL(url, row)) { 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have a row. 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = true; 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optionally query the visits. 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (want_visits) 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(row->id(), visits); 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), success, row, visits); 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1072b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TypedUrlSyncableService* HistoryBackend::GetTypedUrlSyncableService() const { 1073b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return typed_url_syncable_service_.get(); 1074b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 1075b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Segment usage --------------------------------------------------------------- 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteOldSegmentData() { 1079b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteSegmentData(Time::Now() - 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kSegmentDataRetention)); 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QuerySegmentUsage( 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QuerySegmentUsageRequest> request, 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Time from_time, 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_result_count) { 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1091b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(from_time, max_result_count, &request->value.get()); 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is the first time we query segments, invoke 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DeleteOldSegmentData asynchronously. We do this to cleanup old 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entries. 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!segment_queried_) { 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_ = true; 109990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HistoryBackend::DeleteOldSegmentData, this)); 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value.get()); 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::IncreaseSegmentDuration(const GURL& url, 11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time time, 11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta delta) { 1110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string segment_name(VisitSegmentDatabase::ComputeSegmentName(url)); 11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SegmentID segment_id = db_->GetSegmentNamed(segment_name); 11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!segment_id) { 11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!url_id) 11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) segment_id = db_->CreateSegment(url_id, segment_name); 11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!segment_id) 11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SegmentDurationID duration_id; 11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta total_delta; 11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!db_->GetSegmentDuration(segment_id, time, &duration_id, 11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &total_delta)) { 11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->CreateSegmentDuration(segment_id, time, delta); 11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) total_delta += delta; 11312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->SetSegmentDuration(duration_id, total_delta); 11322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::QuerySegmentDuration( 11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<QuerySegmentUsageRequest> request, 11362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Time from_time, 11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int max_result_count) { 11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request->canceled()) 11392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->QuerySegmentDuration(from_time, max_result_count, 11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &request->value.get()); 11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->ForwardResult(request->handle(), &request->value.get()); 11462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keyword visits -------------------------------------------------------------- 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetKeywordSearchTermsForURL(const GURL& url, 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& term) { 1153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the ID for this URL. 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(url, &url_row)) { 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a small possibility the url was deleted before the keyword 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was added. Ignore the request. 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->SetKeywordSearchTermsForURL(url_row.id(), keyword_id, term); 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // details is deleted by BroadcastNotifications. 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KeywordSearchTermDetails* details = new KeywordSearchTermDetails; 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->url = url; 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->keyword_id = keyword_id; 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->term = term; 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications( 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, details); 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllSearchTermsForKeyword( 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id) { 1178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteAllSearchTermsForKeyword(keyword_id); 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky): bug 1168470. Need to move from archive dbs too. 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetMostRecentKeywordSearchTerms( 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request, 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& prefix, 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_count) { 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetMostRecentKeywordSearchTerms(keyword_id, prefix, max_count, 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &(request->value)); 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Downloads ------------------------------------------------------------------- 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HistoryBackend::GetNextDownloadId(uint32* next_id) { 1204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 12057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db_->GetNextDownloadId(next_id); 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get all the download entries from the database. 12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::QueryDownloads(std::vector<DownloadRow>* rows) { 1210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->QueryDownloads(rows); 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Update a particular download entry. 12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::UpdateDownload(const history::DownloadRow& data) { 1216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->UpdateDownload(data); 12192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::CreateDownload(const history::DownloadRow& history_info, 12237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool* success) { 1224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 12267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *success = db_->CreateDownload(history_info); 12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HistoryBackend::RemoveDownloads(const std::set<uint32>& ids) { 1231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 12337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_before = db_->CountDownloads(); 12342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks started_removing = base::TimeTicks::Now(); 12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HistoryBackend uses a long-running Transaction that is committed 12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // periodically, so this loop doesn't actually hit the disk too hard. 12377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (std::set<uint32>::const_iterator it = ids.begin(); 12387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch it != ids.end(); ++it) { 12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->RemoveDownload(*it); 12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScheduleCommit(); 12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks finished_removing = base::TimeTicks::Now(); 12437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_after = db_->CountDownloads(); 12447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 12457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_LE(downloads_count_after, downloads_count_before); 12467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (downloads_count_after > downloads_count_before) 12477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 12487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t num_downloads_deleted = downloads_count_before - downloads_count_after; 12497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCount", 12507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch num_downloads_deleted); 12517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::TimeDelta micros = (1000 * (finished_removing - started_removing)); 12527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTime", micros); 12537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (num_downloads_deleted > 0) { 12547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTimePerRecord", 12557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (1000 * micros) / num_downloads_deleted); 12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_GE(ids.size(), num_downloads_deleted); 12587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ids.size() < num_downloads_deleted) 12597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 12607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCountNotRemoved", 12617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ids.size() - num_downloads_deleted); 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryHistory(scoped_refptr<QueryHistoryRequest> request, 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& text_query, 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const QueryOptions& options) { 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text_query.empty()) { 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Basic history query for the main database. 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryHistoryBasic(db_.get(), db_.get(), options, &request->value); 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now query the archived database. This is a bit tricky because we don't 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to query it if the queried time range isn't going to find anything 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in it. 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1171036: do blimpie querying for the archived database 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as well. 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if (archived_db_.get() && 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expirer_.GetCurrentArchiveTime() - TimeDelta::FromDays(7)) { 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Text history query. 1286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryHistoryText(db_.get(), db_.get(), text_query, options, 1287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &request->value); 1288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (archived_db_.get() && 1289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expirer_.GetCurrentArchiveTime() >= options.begin_time) { 1290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryHistoryText(archived_db_.get(), archived_db_.get(), text_query, 1291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options, &request->value); 1292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.QueryHistory", 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic time-based querying of history. 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryHistoryBasic(URLDatabase* url_db, 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase* visit_db, 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const QueryOptions& options, 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryResults* result) { 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First get all visits. 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 13092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_more_results = visit_db->GetVisibleVisitsInRange(options, &visits); 13102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount()); 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now add them and the URL rows to the results. 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLResult url_result; 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); i++) { 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VisitRow visit = visits[i]; 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a result row for this visit, get the URL info from the DB. 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_db->GetURLRow(visit.url_id, &url_result)) { 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to get id " << visit.url_id 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " from history.urls."; 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // DB out of sync and URL doesn't exist, try to recover. 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_result.url().is_valid()) { 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Got invalid URL from history.urls with id " 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << visit.url_id << ": " 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << url_result.url().possibly_invalid_spec(); 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Don't report invalid URLs in case of corruption. 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The archived database may be out of sync with respect to starring, 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // titles, last visit date, etc. Therefore, we query the main DB if the 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current URL database is not the main one. 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_db == db_.get()) { 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently querying the archived DB, update with the main database to 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // catch any interesting stuff. This will update it if it exists in the 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main DB, and do nothing otherwise. 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetRowForURL(url_result.url(), &url_result); 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_result.set_visit_time(visit.visit_time); 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set whether the visit was blocked for a managed user by looking at the 1344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // transition type. 1345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_result.set_blocked_visit( 1346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0); 1347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't set any of the query-specific parts of the URLResult, since 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // snippets and stuff don't apply to basic querying. 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->AppendURLBySwapping(&url_result); 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_more_results && options.begin_time <= first_recorded_time_) 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->set_reached_beginning(true); 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Text-based querying of history. 1358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::QueryHistoryText(URLDatabase* url_db, 1359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitDatabase* visit_db, 1360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const string16& text_query, 1361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const QueryOptions& options, 1362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryResults* result) { 1363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLRows text_matches; 1364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_db->GetTextMatches(text_query, &text_matches); 1365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<URLResult> matching_visits; 1367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitVector visits; // Declare outside loop to prevent re-construction. 1368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < text_matches.size(); i++) { 1369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const URLRow& text_match = text_matches[i]; 1370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get all visits for given URL match. 1371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch visit_db->GetVisitsForURLWithOptions(text_match.id(), options, &visits); 1372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < visits.size(); j++) { 1373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult url_result(text_match); 1374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_result.set_visit_time(visits[j].visit_time); 1375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch matching_visits.push_back(url_result); 1376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::sort(matching_visits.begin(), matching_visits.end(), 1380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult::CompareVisitTime); 1381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t max_results = options.max_count == 0 ? 1383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::numeric_limits<size_t>::max() : static_cast<int>(options.max_count); 1384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (std::vector<URLResult>::iterator it = matching_visits.begin(); 1385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it != matching_visits.end() && result->size() < max_results; ++it) { 1386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->AppendURLBySwapping(&(*it)); 1387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (matching_visits.size() == result->size() && 1390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options.begin_time <= first_recorded_time_) 1391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->set_reached_beginning(true); 1392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Frontend to GetMostRecentRedirectsFrom from the history thread. 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsFrom( 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsFrom(url, &request->value); 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsTo( 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsTo(url, &request->value); 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetVisibleVisitCountToHost( 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetVisibleVisitCountToHostRequest> request, 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time first_visit; 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool success = db_.get() && 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisibleVisitCountToHost(url, &count, &first_visit); 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), success, count, first_visit); 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryTopURLsAndRedirects( 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryTopURLsAndRedirectsRequest> request, 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count) { 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1431b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), false, NULL, NULL); 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<GURL>* top_urls = &request->value.a; 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectMap* redirects = &request->value.b; 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - base::TimeDelta::FromDays(90), 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_urls->push_back(data[i]->GetURL()); 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RefCountedVector<GURL>* list = new RefCountedVector<GURL>; 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(top_urls->back(), &list->data); 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*redirects)[top_urls->back()] = list; 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), true, top_urls, redirects); 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Will replace QueryTopURLsAndRedirectsRequest. 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLs( 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryMostVisitedURLsRequest> request, 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back) { 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1461b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), MostVisitedURLList()); 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result = &request->value; 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryMostVisitedURLsImpl(result_count, days_back, result); 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), *result); 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryFilteredURLs( 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryFilteredURLsRequest> request, 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::VisitFilter& filter, 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool extended_info) { 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time request_start = base::Time::Now(); 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1482b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), FilteredURLList()); 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetDirectVisitsDuringTimes(filter, 0, &visits); 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, double> score_map; 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score_map[visits[i].url_id] += filter.GetVisitScore(visits[i]); 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(georgey): experiment with visit_segment database granularity (it is 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // currently 24 hours) to use it directly instead of using visits database, 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which is considerably slower. 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.reserve(score_map.size()); 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<URLID, double>::iterator it = score_map.begin(); 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != score_map.end(); ++it) { 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* pud = new PageUsageData(it->first); 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pud->SetScore(it->second); 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.push_back(pud); 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Limit to the top |result_count| results. 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(data.begin(), data.end(), PageUsageData::Predicate); 15102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result_count && implicit_cast<int>(data.size()) > result_count) 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.resize(result_count); 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetURLRow(data[i]->GetID(), &info)) { 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetURL(info.url()); 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetTitle(info.title()); 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURLList& result = request->value; 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURL url(*current_data); 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extended_info) { 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(current_data->GetID(), &visits); 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.size() > 0) { 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.total_visits = visits.size(); 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.duration_opened += 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits[i].visit_duration.InSeconds(); 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits[i].visit_time > url.extended_info.last_visit_time) { 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.last_visit_time = visits[i].visit_time; 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(macourteau): implement the url.extended_info.visits stat. 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.push_back(url); 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delta_time = std::max(1, std::min(999, 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>((base::Time::Now() - request_start).InMilliseconds()))); 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATIC_HISTOGRAM_POINTER_BLOCK( 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NewTabPage.SuggestedSitesLoadTime", 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(delta_time), 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LinearHistogram::FactoryGet("NewTabPage.SuggestedSitesLoadTime", 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1000, 100, base::Histogram::kUmaTargetedHistogramFlag)); 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), result); 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLsImpl(int result_count, 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back, 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result) { 1558b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromDays(days_back), 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects; 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(current_data->GetURL(), &redirects); 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL url = MakeMostVisitedURL(*current_data, redirects); 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->push_back(url); 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsFromSpecificVisit( 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, history::RedirectList* redirects) { 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow any redirects from the given visit and add them to the list. 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It *should* be impossible to get a circular chain here, but we check 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just in case to avoid infinite loops. 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectFromVisit(cur_visit, &cur_visit, &cur_url)) { 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsToSpecificVisit( 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow redirects going to cur_visit. These are added to |redirects| in 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the order they are found. If a redirect chain looks like A -> B -> C and 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |cur_visit| = C, redirects will be {B, A} in that order. 1599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectToVisit(cur_visit, &cur_visit, &cur_url)) { 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsFrom( 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& from_url, 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1619b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID from_url_id = db_->GetRowForURL(from_url, NULL); 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(from_url_id, NULL); 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsFromSpecificVisit(cur_visit, redirects); 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsTo( 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& to_url, 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1635b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID to_url_id = db_->GetRowForURL(to_url, NULL); 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(to_url_id, NULL); 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsToSpecificVisit(cur_visit, redirects); 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleAutocomplete(HistoryURLProvider* provider, 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryURLProviderParams* params) { 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExecuteWithDB should handle the NULL database case. 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->ExecuteWithDB(this, db_.get(), params); 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetPageThumbnail( 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image* thumbnail, 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ThumbnailScore& score) { 1657b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_row); 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->SetPageThumbnail(url, url_id, thumbnail, score, 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_row.last_visit()); 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetPageThumbnail( 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetPageThumbnailRequest> request, 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url) { 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedBytes> data; 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetPageThumbnailDirectly(page_url, &data); 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), data); 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetPageThumbnailDirectly( 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedBytes>* data) { 1685b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *data = new base::RefCountedBytes; 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Time the result. 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirects; 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id; 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there are some redirects, try to get a thumbnail from the last 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirect destination. 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetMostRecentRedirectsFrom(page_url, &redirects) && 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !redirects.empty()) { 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((url_id = db_->GetRowForURL(redirects.back(), NULL))) 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = thumbnail_db_->GetPageThumbnail(url_id, &(*data)->data()); 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have a thumbnail from redirects, try the URL directly. 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!success) { 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((url_id = db_->GetRowForURL(page_url, NULL))) 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = thumbnail_db_->GetPageThumbnail(url_id, &(*data)->data()); 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this rare case, we start to mine the older redirect sessions 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the visit table to try to find a thumbnail. 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!success) { 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = GetThumbnailFromOlderRedirect(page_url, &(*data)->data()); 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!success) 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *data = NULL; // This will tell the callback there was an error. 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.GetPageThumbnail", 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::MigrateThumbnailsDatabase() { 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no History DB, we can't record that the migration was done. 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It will be recorded on the next run. 1726b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no thumbnail DB, we can still record a successful migration. 1728b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->RenameAndDropThumbnails(GetThumbnailFileName(), 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconsFileName()); 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->ThumbnailMigrationDone(); 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1736bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid HistoryBackend::DeleteFTSIndexDatabases() { 1737bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Find files on disk matching the text databases file pattern so we can 1738bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // quickly test for and delete them. 1739bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath::StringType filepattern = 1740bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch FILE_PATH_LITERAL("History Index *"); 1741bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FileEnumerator enumerator( 1742bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch history_dir_, false, base::FileEnumerator::FILES, filepattern); 1743bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch int num_databases_deleted = 0; 1744bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath current_file; 1745bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch while (!(current_file = enumerator.Next()).empty()) { 1746bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (sql::Connection::Delete(current_file)) 1747bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted++; 1748bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 1749bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch UMA_HISTOGRAM_COUNTS("History.DeleteFTSIndexDatabases", 1750bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted); 1751bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 1752bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetThumbnailFromOlderRedirect( 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<unsigned char>* data) { 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Look at a few previous visit sessions. 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector older_sessions; 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID page_url_id = db_->GetRowForURL(page_url, NULL); 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kVisitsToSearchForThumbnail = 4; 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetMostRecentVisitsForURL( 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_url_id, kVisitsToSearchForThumbnail, &older_sessions); 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate across all those previous visits, and see if any of the 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // final destinations of those redirect chains have a good thumbnail 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for us. 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (VisitVector::const_iterator it = older_sessions.begin(); 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !success && it != older_sessions.end(); ++it) { 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirects; 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->visit_id) { 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsFromSpecificVisit(it->visit_id, &redirects); 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!redirects.empty()) { 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id; 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((url_id = db_->GetRowForURL(redirects.back(), NULL))) 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = thumbnail_db_->GetPageThumbnail(url_id, data); 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFavicons( 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 17882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 178990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(NULL, icon_urls, icon_types, 17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFaviconsForURL( 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 180090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 18012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(bitmap_results); 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconsFromDB(page_url, icon_types, desired_size_in_dip, 18032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::GetFaviconForID( 180790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID favicon_id, 18082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int desired_size_in_dip, 18092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ScaleFactor desired_scale_factor, 181090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 181190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> favicon_ids; 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ui::ScaleFactor> desired_scale_factors; 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors.push_back(desired_scale_factor); 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get results from DB. 18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, 18182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, 18192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, 18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetch( 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 18282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 182990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 18302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(&page_url, icon_urls, icon_types, 18312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 18322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::MergeFavicon( 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 18372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 183890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type, 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedMemory> bitmap_data, 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& pixel_size) { 1841b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 184490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID favicon_id = 184590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_id) { 18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There is no favicon at |icon_url|, create it. 1849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch favicon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 18502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(favicon_id, &bitmap_id_sizes); 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is already a favicon bitmap of |pixel_size| at |icon_url|, 18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // replace it. 18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool bitmap_identical = false; 18582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool replaced_bitmap = false; 18592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes[i].pixel_size == pixel_size) { 18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsFaviconBitmapDataEqual(bitmap_id_sizes[i].bitmap_id, bitmap_data)) { 18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id_sizes[i].bitmap_id, base::Time::Now()); 18642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_identical = true; 18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 18662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id_sizes[i].bitmap_id, 18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_data, base::Time::Now()); 18682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) replaced_bitmap = true; 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a vector of the pixel sizes of the favicon bitmaps currently at 18752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url|. 18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size> favicon_sizes; 18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) 18782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmap_id_sizes[i].pixel_size); 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!replaced_bitmap && !bitmap_identical) { 18812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set the preexisting favicon bitmaps as expired as the preexisting favicon 18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmaps are not consistent with the merged in data. 18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(favicon_id); 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete an arbitrary favicon bitmap to avoid going over the limit of 18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |kMaxFaviconBitmapsPerIconURL|. 18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes.size() >= kMaxFaviconBitmapsPerIconURL) { 18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[0].bitmap_id); 18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.erase(favicon_sizes.begin()); 18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, bitmap_data, base::Time::Now(), 18922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pixel_size); 18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(pixel_size); 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A site may have changed the favicons that it uses for |page_url|. 18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Example Scenario: 18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // page_url = news.google.com 18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Intial State: www.google.com/favicon.ico 16x16, 32x32 19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // MergeFavicon(news.google.com, news.google.com/news_specific.ico, ..., 19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ..., 16x16) 19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulties: 19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1. Sync requires that a call to GetFaviconsForURL() returns the 19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |bitmap_data| passed into MergeFavicon(). 19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - It is invalid for the 16x16 bitmap for www.google.com/favicon.ico to 19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stay mapped to news.google.com because it would be unclear which 16x16 19082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap should be returned via GetFaviconsForURL(). 19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2. www.google.com/favicon.ico may be mapped to more than just 19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com (eg www.google.com). 19122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - The 16x16 bitmap cannot be deleted from www.google.com/favicon.ico 19132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // To resolve these problems, we copy all of the favicon bitmaps previously 19152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // mapped to news.google.com (|page_url|) and add them to the favicon at 19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com/news_specific.ico (|icon_url|). The favicon sizes for 19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url| are set to default to indicate that |icon_url| has incomplete 19182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // / incorrect data. 19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficlty 1: All but news.google.com/news_specific.ico are unmapped from 19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com 19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulty 2: The favicon bitmaps for www.google.com/favicon.ico are not 19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // modified. 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 19252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_type, &icon_mappings); 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy the favicon bitmaps mapped to |page_url| to the favicon at |icon_url| 19282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // till the limit of |kMaxFaviconBitmapsPerIconURL| is reached. 19292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) { 19302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 19312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings[i].icon_url == icon_url) 19342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmap> bitmaps_to_copy; 19372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmaps(icon_mappings[i].icon_id, 19382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &bitmaps_to_copy); 19392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t j = 0; j < bitmaps_to_copy.size(); ++j) { 19402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do not add a favicon bitmap at a pixel size for which there is already 19412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a favicon bitmap mapped to |icon_url|. The one there is more correct 19422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and having multiple equally sized favicon bitmaps for |page_url| is 19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ambiguous in terms of GetFaviconsForURL(). 19442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(), 19452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.end(), bitmaps_to_copy[j].pixel_size); 19462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != favicon_sizes.end()) 19472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 19482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add the favicon bitmap as expired as it is not consistent with the 19502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // merged in data. 19512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, 19522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].bitmap_data, base::Time(), 19532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].pixel_size); 19542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmaps_to_copy[j].pixel_size); 19552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 19572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 19582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update the favicon mappings such that only |icon_url| is mapped to 19622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |page_url|. 19632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool mapping_changed = false; 19642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings.size() != 1 || icon_mappings[0].icon_url != icon_url) { 196590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> favicon_ids; 19662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_ids.push_back(favicon_id); 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, favicon_ids); 19682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mapping_changed = true; 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mapping_changed || !bitmap_identical) 19722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFavicons( 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 197890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type, 197990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconBitmapData>& favicon_bitmap_data) { 1980b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(ValidateSetFaviconsParams(favicon_bitmap_data)); 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build map of FaviconBitmapData for each icon url. 198690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) typedef std::map<GURL, std::vector<chrome::FaviconBitmapData> > 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL; 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL grouped_by_icon_url; 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) grouped_by_icon_url[icon_url].push_back(favicon_bitmap_data[i]); 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Track whether the method modifies or creates any favicon bitmaps, favicons 19952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // or icon mappings. 19962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool data_modified = false; 19972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 199890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> icon_ids; 19992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapDataByIconURL::const_iterator it = grouped_by_icon_url.begin(); 20002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != grouped_by_icon_url.end(); ++it) { 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = it->first; 200290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID icon_id = 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 20042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!icon_id) { 20062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(pkotwicz): Remove the favicon sizes attribute from 20072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ThumbnailDatabase::AddFavicon(). 2008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 20092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified = true; 20102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_ids.push_back(icon_id); 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data_modified) 20142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, &data_modified); 20152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 20162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, NULL); 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified |= 20202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids); 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data_modified) { 20232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send notification to the UI as an icon mapping, favicon, or favicon 20242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap was changed by this function. 20252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 20262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) { 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2033b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !thumbnail_db_->GetIconMappingsForPageURL(page_url, 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings)) 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(m->icon_id); 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloneFavicons(const GURL& old_page_url, 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& new_page_url) { 2047b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent cross-domain cloning. 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetImportedFavicons( 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ImportedFaviconUsage>& favicon_usage) { 2060b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time now = Time::Now(); 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Track all URLs that had their favicons set or updated. 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<GURL> favicons_changed; 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_usage.size(); i++) { 206990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL( 207090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) favicon_usage[i].favicon_url, chrome::FAVICON, NULL); 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_id) { 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This favicon doesn't exist yet, so we create it using the given data. 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Pass in real pixel size. 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_id = thumbnail_db_->AddFavicon( 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_usage[i].favicon_url, 207690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FAVICON, 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new base::RefCountedBytes(favicon_usage[i].png_data), 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now, 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size()); 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the mapping from all the URLs to the favicon. 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service = GetBookmarkService(); 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator url = favicon_usage[i].urls.begin(); 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url != favicon_usage[i].urls.end(); ++url) { 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*url, &url_row)) { 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL is present as a bookmark, add the url in history to 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save the favicon mapping. This will match with what history db does 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for regular bookmarked URLs with favicons - when history db is 20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cleaned, we keep an entry in the db with 0 visits as long as that 20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // url is bookmarked. 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service && bookmark_service_->IsBookmarked(*url)) { 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(*url); 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(0); 20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(0); 20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(base::Time()); 20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 210490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL( 210590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *url, chrome::FAVICON, NULL)) { 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is present in history, update the favicon *only* if it is not 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set already. 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicons_changed.empty()) { 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the notification about the changed favicon URLs. 211790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FaviconChangedDetails* changed_details = new FaviconChangedDetails; 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.swap(favicons_changed); 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details); 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetchImpl( 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL* page_url, 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 21292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 213090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |page_url| is specified, |icon_types| must be either a single icon 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // type or icon types which are equivalent. 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!page_url || 213490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_types == chrome::FAVICON || 213590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_types == chrome::TOUCH_ICON || 213690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_types == chrome::TOUCH_PRECOMPOSED_ICON || 213790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_types == (chrome::TOUCH_ICON | chrome::TOUCH_PRECOMPOSED_ICON)); 21382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results->clear(); 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 214490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> favicon_ids; 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The icon type for which the mappings will the updated and data will be 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned. 214890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType selected_icon_type = chrome::INVALID_ICON; 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_urls.size(); ++i) { 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = icon_urls[i]; 215290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type_out; 215390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const chrome::FaviconID favicon_id = 215490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL( 215590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_url, icon_types, &icon_type_out); 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_id) { 21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return and update icon mappings only for the largest icon type. As 21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |icon_urls| is not sorted in terms of icon type, clear |favicon_ids| 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if an |icon_url| with a larger icon type is found. 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out > selected_icon_type) { 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_icon_type = icon_type_out; 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.clear(); 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out == selected_icon_type) 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_url && !favicon_ids.empty()) { 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_updated = 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(*page_url, selected_icon_type, 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids); 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mappings_updated) { 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(*page_url); 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip, 21812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconBitmaps( 218590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID icon_id, 218690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconBitmapData>& favicon_bitmap_data, 21872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* favicon_bitmaps_changed) { 21882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = false; 21902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes); 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 219490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapData> to_add = favicon_bitmap_data; 21952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 21972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& pixel_size = bitmap_id_sizes[i].pixel_size; 219890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapData>::iterator match_it = to_add.end(); 219990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (std::vector<chrome::FaviconBitmapData>::iterator it = to_add.begin(); 22002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != to_add.end(); ++it) { 22012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->pixel_size == pixel_size) { 22022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) match_it = it; 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 22072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id = bitmap_id_sizes[i].bitmap_id; 22082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (match_it == to_add.end()) { 22092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id); 22102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 22112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 22122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 22142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed && 22152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !*favicon_bitmaps_changed && 22162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsFaviconBitmapDataEqual(bitmap_id, match_it->bitmap_data)) { 22172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 22182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id, base::Time::Now()); 22192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 22202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id, match_it->bitmap_data, 22212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now()); 22222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 22232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 22242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 22252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 22262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) to_add.erase(match_it); 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < to_add.size(); ++i) { 22312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(icon_id, to_add[i].bitmap_data, 22322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now(), to_add[i].pixel_size); 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 22352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistoryBackend::ValidateSetFaviconsParams( 224090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconBitmapData>& favicon_bitmap_data) const { 22412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::map<GURL, size_t> BitmapsPerIconURL; 22422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BitmapsPerIconURL num_bitmaps_per_icon_url; 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 2244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!favicon_bitmap_data[i].bitmap_data.get()) 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 22482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!num_bitmaps_per_icon_url.count(icon_url)) 22492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_bitmaps_per_icon_url[icon_url] = 1u; 22502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 22512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++num_bitmaps_per_icon_url[icon_url]; 22522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 22532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 22542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (num_bitmaps_per_icon_url.size() > kMaxFaviconsPerPage) 22552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapsPerIconURL::const_iterator it = num_bitmaps_per_icon_url.begin(); 22582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != num_bitmaps_per_icon_url.end(); ++it) { 22592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->second > kMaxFaviconBitmapsPerIconURL) 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistoryBackend::IsFaviconBitmapDataEqual( 22662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id, 22672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<base::RefCountedMemory>& new_bitmap_data) { 2268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!new_bitmap_data.get()) 22692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedMemory> original_bitmap_data; 22722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmap(bitmap_id, 22732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 22742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &original_bitmap_data, 22752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL); 22762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_bitmap_data->Equals(original_bitmap_data); 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconsFromDB( 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 228490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* favicon_bitmap_results) { 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(favicon_bitmap_results); 22862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_bitmap_results->clear(); 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Time the query. 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get FaviconIDs for |page_url| and one of |icon_types|. 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types, 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings); 229890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> favicon_ids; 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(icon_mappings[i].icon_id); 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populate |favicon_bitmap_results| and |icon_url_sizes|. 23032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = GetFaviconBitmapResultsForBestMatch(favicon_ids, 23042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, favicon_bitmap_results); 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 23072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success && !favicon_bitmap_results->empty(); 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconBitmapResultsForBestMatch( 231190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconID>& candidate_favicon_ids, 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 231490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* favicon_bitmap_results) { 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->clear(); 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate_favicon_ids.empty()) 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the FaviconID and the FaviconBitmapIDs which best match 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |desired_size_in_dip| and |desired_scale_factors|. 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Select bitmap results from multiple favicons once 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content::FaviconStatus supports multiple icon URLs. 232490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID best_favicon_id = 0; 23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapID> best_bitmap_ids; 23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float highest_score = kSelectFaviconFramesInvalidScore; 23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < candidate_favicon_ids.size(); ++i) { 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(candidate_favicon_ids[i], 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_id_sizes); 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build vector of gfx::Size from |bitmap_id_sizes|. 23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<gfx::Size> sizes; 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < bitmap_id_sizes.size(); ++j) 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizes.push_back(bitmap_id_sizes[j].pixel_size); 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<size_t> candidate_bitmap_indices; 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score = 0; 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFaviconFrameIndices(sizes, 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors, 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_size_in_dip, 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &candidate_bitmap_indices, 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &score); 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (score > highest_score) { 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) highest_score = score; 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_favicon_id = candidate_favicon_ids[i], 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.clear(); 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < candidate_bitmap_indices.size(); ++j) { 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t candidate_index = candidate_bitmap_indices[j]; 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.push_back( 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_id_sizes[candidate_index].bitmap_id); 23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct FaviconBitmapResults from |best_favicon_id| and 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |best_bitmap_ids|. 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL icon_url; 235990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type; 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url, 2361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &icon_type)) { 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < best_bitmap_ids.size(); ++i) { 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_updated; 236790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconBitmapResult bitmap_result; 23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_url = icon_url; 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_type = icon_type; 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(best_bitmap_ids[i], 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &last_updated, 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.bitmap_data, 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.pixel_size)) { 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap_result.is_valid()) 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->push_back(bitmap_result); 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPageAndRedirects( 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 238790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type, 238890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconID>& icon_ids) { 2389b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find all the pages whose favicons we should set, we want to set it for 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all the pages in the redirect chain if it redirected. 23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirects; 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirects); 23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save page <-> favicon associations. 24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (history::RedirectList::const_iterator i(redirects.begin()); 24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != redirects.end(); ++i) { 24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed |= SetFaviconMappingsForPage(*i, icon_type, icon_ids); 24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPage( 24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 240990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type, 241090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconID>& icon_ids) { 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(icon_ids.size(), kMaxFaviconsPerPage); 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Two icon types are considered 'equivalent' if one of the icon types is 24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TOUCH_ICON and the other is TOUCH_PRECOMPOSED_ICON. 24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the icon mappings from |page_url| for |icon_type| to the favicons 24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with |icon_ids|. Mappings for |page_url| to favicons of type |icon_type| 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whose FaviconID is not in |icon_ids| are removed. All icon mappings for 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |page_url| to favicons of a type equivalent to |icon_type| are removed. 24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any favicons which are orphaned as a result of the removal of the 24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon mappings. 24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 242490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> unmapped_icon_ids = icon_ids; 24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings); 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 243190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID>::iterator icon_id_it = std::find( 24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.begin(), unmapped_icon_ids.end(), m->icon_id); 24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the icon mapping already exists, avoid removing it and adding it back. 24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_id_it != unmapped_icon_ids.end()) { 24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.erase(icon_id_it); 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 244090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if ((icon_type == chrome::TOUCH_ICON && 244190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) m->icon_type == chrome::TOUCH_PRECOMPOSED_ICON) || 244290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (icon_type == chrome::TOUCH_PRECOMPOSED_ICON && 244390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) m->icon_type == chrome::TOUCH_ICON) || (icon_type == m->icon_type)) { 24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteIconMapping(m->mapping_id); 24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removing the icon mapping may have orphaned the associated favicon so 24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we must recheck it. This is not super fast, but this case will get 24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered rarely, since normally a page will always map to the same 24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon IDs. It will mostly happen for favicons we import. 24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->HasMappingFor(m->icon_id)) 24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteFavicon(m->icon_id); 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < unmapped_icon_ids.size(); ++i) { 24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(page_url, unmapped_icon_ids[i]); 24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetCachedRecentRedirects( 24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirect_list) { 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(page_url); 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *redirect_list = iter->second; 24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The redirect chain should have the destination URL as the last item. 24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirect_list->empty()); 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirect_list->back() == page_url); 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No known redirects, construct mock redirect chain containing |page_url|. 24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_list->push_back(page_url); 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SendFaviconChangedNotificationForPageAndRedirects( 24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url) { 24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirect_list; 24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirect_list); 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 248490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FaviconChangedDetails* changed_details = new FaviconChangedDetails; 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirect_list.size(); ++i) 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.insert(redirect_list[i]); 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details); 24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Commit() { 2493b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that a commit may not actually have been scheduled if a caller 24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // explicitly calls this instead of using ScheduleCommit. Likewise, we 24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may reset the flag written by a pending commit. But this is OK! It 24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will merely cause extra commits (which is kind of the idea). We 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could optimize more for this case (we may get two extra commits in 25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some cases) but it hasn't been important yet. 25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; 25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 0) << 25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Somebody left a transaction open"; 25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->CommitTransaction(); 25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleCommit() { 2522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) 25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = new CommitLaterTask(this); 252590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()), 25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); 25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CancelScheduledCommit() { 2532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) { 25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_->Cancel(); 25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = NULL; 25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTaskImpl() { 2539b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // db went away, release all the refs. 25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseDBTasks(); 25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any canceled tasks. 25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!db_task_requests_.empty() && db_task_requests_.front()->canceled()) { 25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.front()->Release(); 25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_task_requests_.empty()) 25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the first task. 25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDBTaskRequest* request = db_task_requests_.front(); 25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->value->RunOnDBThread(this, db_.get())) { 25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The task is done. Notify the callback. 25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(); 25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We AddRef'd the request before adding, need to release it now. 25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->Release(); 25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tasks wants to run some more. Schedule it at the end of current tasks. 25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request); 25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And process it after an invoke later. 256590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTaskImpl, this)); 25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ReleaseDBTasks() { 25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::list<HistoryDBTaskRequest*>::iterator i = 25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.begin(); i != db_task_requests_.end(); ++i) { 25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->Release(); 25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.clear(); 25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generic operations 25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { 25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURLs(urls); 25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURL(const GURL& url) { 25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(url); 25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ExpireHistoryBetween( 26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<GURL>& restrict_urls, 26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time begin_time, 26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_time) { 2606b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 26072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (begin_time.is_null() && (end_time.is_null() || end_time.is_max()) && 26082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) restrict_urls.empty()) { 26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Special case deleting all history so it can be faster and to reduce the 26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // possibility of an information leak. 26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteAllHistory(); 26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clearing parts of history, have the expirer do the depend 26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.ExpireHistoryBetween(restrict_urls, begin_time, end_time); 26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, 26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we want to get it on disk ASAP. 26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (begin_time <= first_recorded_time_) 26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 26242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 26252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistoryForTimes( 26272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::set<base::Time>& times, 26282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time begin_time, base::Time end_time) { 2629b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (times.empty() || !db_) 26302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 26312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.begin() >= begin_time) 26332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Min time is before begin time: " 26342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime(); 26352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.rbegin() < end_time) 26362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Max time is after end time: " 26372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime(); 26382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history::QueryOptions options; 26402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.begin_time = begin_time; 26412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.end_time = end_time; 26422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES; 26432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryResults results; 26442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryHistoryBasic(db_.get(), db_.get(), options, &results); 26452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1st pass: find URLs that are visited at one of |times|. 26472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<GURL> urls; 26482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 26492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times.count(results[i].visit_time()) > 0) 26502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) urls.insert(results[i].url()); 26512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.empty()) 26532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 26542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2nd pass: collect all visit times of those URLs. 26562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::Time> times_to_expire; 26572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 26582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.count(results[i].url())) 26592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.push_back(results[i].visit_time()); 26602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put the times in reverse chronological order and remove 26632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // duplicates (for expirer_.ExpireHistoryForTimes()). 26642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::sort(times_to_expire.begin(), times_to_expire.end(), 26652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::greater<base::Time>()); 26662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.erase( 26672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::unique(times_to_expire.begin(), times_to_expire.end()), 26682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.end()); 26692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Expires by times and commit. 26712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!times_to_expire.empty()); 26722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryForTimes(times_to_expire); 26732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 26742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(times_to_expire.back() >= first_recorded_time_); 26762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if we expired it. 26772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times_to_expire.back() == first_recorded_time_) 26782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 26792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistory( 26822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<history::ExpireHistoryArgs>& expire_list) { 2683b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 26842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool update_first_recorded_time = false; 26852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<history::ExpireHistoryArgs>::const_iterator it = 26872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.begin(); it != expire_list.end(); ++it) { 26882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryBetween(it->urls, it->begin_time, it->end_time); 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->begin_time < first_recorded_time_) 26912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) update_first_recorded_time = true; 26922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 26942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if any deletion might have affected it. 26962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (update_first_recorded_time) 26972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 26982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) { 2702b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*i, &url_row)) 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // The URL isn't in the db; nothing to do. 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(url_row.id(), &visits); 27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.empty()) 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(*i); // There are no more visits; nuke the URL. 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void HistoryBackend::DatabaseErrorCallback(int error, sql::Statement* stmt) { 27197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!scheduled_kill_db_ && sql::IsErrorCatastrophic(error)) { 27207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = true; 27217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Don't just do the close/delete here, as we are being called by |db| and 27227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // that seems dangerous. 27237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // TODO(shess): Consider changing KillHistoryDatabase() to use 27247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // RazeAndClose(). Then it can be cleared immediately. 27257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::MessageLoop::current()->PostTask( 27267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) FROM_HERE, 27277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::KillHistoryDatabase, this)); 27287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 27297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 27307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::KillHistoryDatabase() { 27327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = false; 2733b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rollback transaction because Raze() cannot be called from within a 27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction. 27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RollbackTransaction(); 27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = db_->Raze(); 27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success); 27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The expirer keeps tabs on the active databases. Tell it about the 27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // databases which will be closed. 2749bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch expirer_.SetDatabases(NULL, NULL, NULL); 27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). 27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTask( 27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryDBTaskRequest> request) { 2758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(request.get()); 27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool task_scheduled = !db_task_requests_.empty(); 27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we up the refcount of the request. ProcessDBTaskImpl will 27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release when done with the task. 27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->AddRef(); 27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request.get()); 27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!task_scheduled) { 27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No other tasks are scheduled. Process request now. 27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDBTaskImpl(); 27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::BroadcastNotifications( 27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDetails* details_deleted) { 27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |delegate_| may be NULL if |this| is in the process of closing (closed by 2777b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // HistoryService -> HistoryBackend::Closing(). 2778b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->BroadcastNotifications(type, details_deleted); 27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete details_deleted; 27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2784b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void HistoryBackend::NotifySyncURLsDeleted(bool all_history, 2785b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool archived, 2786b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRows* rows) { 2787b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 2788b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsDeleted(all_history, archived, rows); 2789b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 2790b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Deleting -------------------------------------------------------------------- 27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllHistory() { 27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our approach to deleting all history is: 27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Copy the bookmarks and their dependencies to new tables with temporary 27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // names. 27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. Delete the original tables. Since tables can not share pages, we know 27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that any data we don't want to keep is now in an unused page. 27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3. Renaming the temporary tables to match the original. 28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4. Vacuuming the database to delete the unused pages. 28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we are likely to have very few bookmarks and their dependencies 28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compared to all history, this is also much faster than just deleting from 28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original tables directly. 28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the bookmarked URLs. 28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<BookmarkService::URLAndTitle> starred_urls; 28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service = GetBookmarkService(); 28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service) 28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_->GetBookmarks(&starred_urls); 28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRows kept_urls; 28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < starred_urls.size(); i++) { 28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(starred_urls[i].url, &row)) 28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the last visit time so when we write these rows they are "clean." 28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_last_visit(Time()); 28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_visit_count(0); 28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_typed_count(0); 28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.push_back(row); 28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear thumbnail and favicon history. The favicons for the given URLs will 28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be kept. 28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ClearAllThumbnailHistory(&kept_urls)) { 28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Thumbnail history could not be cleared"; 28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We continue in this error case. If the user wants to delete their 28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history, we should delete as much as we can. 28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ClearAllMainHistory will change the IDs of the URLs in kept_urls. Therfore, 28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we clear the list afterwards to make sure nobody uses this invalid data. 28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ClearAllMainHistory(kept_urls)) 28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Main history could not be cleared"; 28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.clear(); 28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2839bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Delete archived history. 2840b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close the database and delete the file. 28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 28432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath archived_file_name = GetArchivedFileName(); 2844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(archived_file_name); 28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now re-initialize the database (which may fail). 28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(new ArchivedDatabase()); 28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!archived_db_->Init(archived_file_name)) { 28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the archived database."; 28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open our long-running transaction on this database. 28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send out the notfication that history is cleared. The in-memory datdabase 28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will pick this up and clear itself. 28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLsDeletedDetails* details = new URLsDeletedDetails; 28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->all_history = true; 2863b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NotifySyncURLsDeleted(true, false, NULL); 28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, details); 28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::ClearAllThumbnailHistory(URLRows* kept_urls) { 2868b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we have no reference to the thumbnail database, maybe there was an 28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error opening it. In this case, we just try to blow it away to try to 28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fix the error if it exists. This may fail, in which case either the 28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file doesn't exist or there's no more we can do. 2873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetThumbnailFileName()); 28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create duplicate icon_mapping, favicon, and favicon_bitmaps tables, this 28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is where the favicons we want to keep will be stored. 28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->InitTemporaryTables()) 28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This maps existing favicon IDs to the ones in the temporary table. 288390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) typedef std::map<chrome::FaviconID, chrome::FaviconID> FaviconMap; 28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconMap copied_favicons; 28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy all unique favicons to the temporary table, and update all the 28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URLs to have the new IDs. 28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::iterator i = kept_urls->begin(); i != kept_urls->end(); ++i) { 28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL(i->url(), &icon_mappings)) 28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 289590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID old_id = m->icon_id; 289690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID new_id; 28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconMap::const_iterator found = copied_favicons.find(old_id); 28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found == copied_favicons.end()) { 28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_id = thumbnail_db_->CopyFaviconAndFaviconBitmapsToTemporaryTables( 29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_id); 29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copied_favicons[old_id] = new_id; 29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We already encountered a URL that used this favicon, use the ID we 29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // previously got. 29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_id = found->second; 29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add Icon mapping, and we don't care wheteher it suceeded or not. 29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddToTemporaryIconMappingTable(i->url(), new_id); 29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO (michaelbai): Add the unit test once AndroidProviderBackend is 29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avaliable in HistoryBackend. 29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->ClearAndroidURLRows(); 29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Drop original favicon_bitmaps, favicons, and icon mapping tables and 29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // replace them with the duplicate tables. Recreate the other tables. This 29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will make the database consistent again. 29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTemporaryTables(); 29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->RecreateThumbnailTable(); 29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to remove all the pages associated with the dropped tables. There 29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must be no transaction open on the table when we do this. We assume that 29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our long-running transaction is open, so we complete it and start it again. 29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 1); 29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->Vacuum(); 29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::ClearAllMainHistory(const URLRows& kept_urls) { 29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the duplicate URL table. We will copy the kept URLs into this. 29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CreateTemporaryURLTable()) 29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert the URLs into the temporary table, we need to keep a map of changed 29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IDs since the ID will be different in the new table. 29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<URLID, URLID> URLIDMap; 29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLIDMap old_to_new; // Maps original ID to new one. 29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); i != kept_urls.end(); 29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID new_id = db_->AddTemporaryURL(*i); 29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_to_new[i->id()] = new_id; 29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the original URL table with the temporary one. 29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CommitTemporaryURLTable()) 29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the old tables and recreate them empty. 29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RecreateAllTablesButURL(); 29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to reclaim the space from the dropped tables. This must be done 29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when there is no transaction open, and we assume that our long-running 29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction is currently open. 29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Vacuum(); 29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkService* HistoryBackend::GetBookmarkService() { 29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service_) 29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_->BlockTillLoaded(); 29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bookmark_service_; 29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { 29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BriefVisitInfo info; 29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.url_id = visit.url_id; 29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.time = visit.visit_time; 29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.transition = visit.transition; 29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have a delegate yet during setup or shutdown, we will drop 29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these notifications. 2980b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->NotifyVisitDBObserversOnAddVisit(info); 29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2984eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 2985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::PopulateMostVisitedURLMap() { 2986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MostVisitedURLList most_visited_urls; 2987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryMostVisitedURLsImpl(kPageVisitStatsMaxTopSites, kSegmentDataRetention, 2988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &most_visited_urls); 2989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_LE(most_visited_urls.size(), kPageVisitStatsMaxTopSites); 2991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < most_visited_urls.size(); ++i) { 2992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].url] = i; 2993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < most_visited_urls[i].redirects.size(); ++j) 2994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].redirects[j]] = i; 2995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2996eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::RecordTopPageVisitStats(const GURL& url) { 2999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int rank = kPageVisitStatsMaxTopSites; 3000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); 3001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it != most_visited_urls_map_.end()) 3002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank = (*it).second; 3003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", 3004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank, kPageVisitStatsMaxTopSites + 1); 3005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 3006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 3007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 3009