history_backend.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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" 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/favicon/favicon_changed_details.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/download_row.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_db_task.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_notifications.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/in_memory_history_backend.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/page_usage_data.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/top_sites.h" 34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/history/typed_url_syncable_service.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/visit_filter.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/importer/imported_favicon_usage.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/favicon_base/select_favicon_frames.h" 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/history/core/browser/history_client.h" 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/history/core/browser/keyword_search_term.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/error_delegate_util.h" 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/android/android_provider_backend.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/* The HistoryBackend consists of two components: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase (stores past 3 months of history) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase (stores a list of URLs) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadDatabase (stores a list of downloads) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase (stores a list of visits for the URLs) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSegmentDatabase (stores groups of URLs for the most visited view). 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ExpireHistoryBackend (manages deleting things older than 3 months) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid RunUnlessCanceled( 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::Closure& closure, 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) { 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!is_canceled.Run()) 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch closure.Run(); 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_ANDROID) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we keep segment data for in days. Currently 3 months. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This value needs to be greater or equal to 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dependency between MostVisitedModel and the history backend. 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kSegmentDataRetention = 90; 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we'll wait to do a commit, so that things are batched together. 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kCommitIntervalSeconds = 10; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of time before we re-fetch the favicon. 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kFaviconRefetchDays = 7; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum number of items we'll allow in the redirect list before 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deleting some. 9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kMaxRedirectCount = 32; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The number of days old a history entry can be before it is considered "old" 9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// and is deleted. 9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const int kExpireDaysThreshold = 90; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The maximum number of top sites to track when recording top page visit stats. 10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const size_t kPageVisitStatsMaxTopSites = 50; 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts from PageUsageData to MostVisitedURL. |redirects| is a 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list of redirects for this URL. Empty list means no redirects. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RedirectList& redirects) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL mv; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.url = page_data.GetURL(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.title = page_data.GetTitle(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirects.empty()) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirects must contain at least the target url. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects = redirects; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mv.redirects[mv.redirects.size() - 1] != mv.url) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last url must be the target url. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mv; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This task is run on a timer so that commits happen at regular intervals 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so they are batched together. The important thing about this class is that 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it supports canceling of the task so the reference to the backend will be 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// freed. The problem is that when history is shutting down, there is likely 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be one of these commits still pending and holding a reference. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The backend can call Cancel to have this task release the reference. The 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// task will still run (if we ever get to processing the event before 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shutdown), but it will not do anything. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that this is a refcounted object and is not a task in itself. It should 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be assigned to a RunnableMethod. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(brettw): bug 1165182: This should be replaced with a 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::WeakPtrFactory which will handle everything automatically (like we do 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in ExpireHistoryBackend). 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CommitLaterTask : public base::RefCounted<CommitLaterTask> { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CommitLaterTask(HistoryBackend* history_backend) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : history_backend_(history_backend) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The backend will call this function if it is being destroyed so that we 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release our reference. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Cancel() { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_ = NULL; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunCommit() { 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (history_backend_.get()) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_->Commit(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCounted<CommitLaterTask>; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~CommitLaterTask() {} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryBackend> history_backend_; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// QueuedHistoryDBTask --------------------------------------------------------- 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 168116680a4aac90f2aa7413d9095a592090648e557Ben MurdochQueuedHistoryDBTask::QueuedHistoryDBTask( 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<HistoryDBTask> task, 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<base::SingleThreadTaskRunner> origin_loop, 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : task_(task), origin_loop_(origin_loop), is_canceled_(is_canceled) { 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(task_); 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(origin_loop_); 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!is_canceled_.is_null()); 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 178116680a4aac90f2aa7413d9095a592090648e557Ben MurdochQueuedHistoryDBTask::~QueuedHistoryDBTask() { 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool QueuedHistoryDBTask::is_canceled() { 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return is_canceled_.Run(); 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool QueuedHistoryDBTask::RunOnDBThread(HistoryBackend* backend, 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch HistoryDatabase* db) { 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return task_->RunOnDBThread(backend, db); 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid QueuedHistoryDBTask::DoneRunOnMainThread() { 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch origin_loop_->PostTask( 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FROM_HERE, 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&RunUnlessCanceled, 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&HistoryDBTask::DoneRunOnMainThread, task_), 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch is_canceled_)); 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HistoryBackend -------------------------------------------------------------- 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistoryBackend::HistoryBackend(const base::FilePath& history_dir, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate, 20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HistoryClient* history_client) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(delegate), 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_dir_(history_dir), 2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_(false), 20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) expirer_(this, history_client), 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recent_redirects_(kMaxRedirectCount), 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_(NULL), 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_(false), 21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) history_client_(history_client) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryBackend::~HistoryBackend() { 214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!scheduled_commit_.get()) << "Deleting without cleanup"; 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_history_db_tasks_.clear(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First close the databases before optionally running the "destroy" task. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!backend_destroy_task_.is_null()) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify an interested party (typically a unit test) that we're done. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(backend_destroy_message_loop_); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_->PostTask(FROM_HERE, backend_destroy_task_); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetAndroidCacheFileName()); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Init(const std::string& languages, bool force_fail) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!force_fail) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitImpl(languages); 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->DBLoaded(); 240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_.reset(new TypedUrlSyncableService(this)); 241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch memory_pressure_listener_.reset(new base::MemoryPressureListener( 242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&HistoryBackend::OnMemoryPressure, base::Unretained(this)))); 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PopulateMostVisitedURLMap(); 245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryBackend::SetOnBackendDestroyTask(base::MessageLoop* message_loop, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& task) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!backend_destroy_task_.is_null()) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Setting more than one destroy task, overriding"; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_ = message_loop; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_task_ = task; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Closing() { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Any scheduled commit will have a reference to us, we must make it 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release that reference before we can be destroyed. 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release our reference to the delegate, this reference will be keeping the 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history service alive. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_.reset(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void HistoryBackend::ClearCachedDataForContextID(ContextID context_id) { 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tracker_.ClearCachedDataForContextID(context_id); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetThumbnailFileName() const { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kThumbnailsFilename); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetFaviconsFileName() const { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kFaviconsFilename); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetArchivedFileName() const { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kArchivedHistoryFilename); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetAndroidCacheFileName() const { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kAndroidCacheFilename); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SegmentID HistoryBackend::GetLastSegmentID(VisitID from_visit) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set is used to detect referrer loops. Should not happen, but can 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the database is corrupt. 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = from_visit; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (visit_id) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow row; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForVisit(visit_id, &row)) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row.segment_id) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row.segment_id; // Found a visit in this change with a segment. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the referrer of this visit, if any. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_id = row.referring_visit; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(visit_id) != visit_set.end()) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in referer chain, giving up"; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(visit_id); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SegmentID HistoryBackend::UpdateSegments( 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID from_visit, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition_type, 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Time ts) { 318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only consider main frames. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!content::PageTransitionIsMainFrame(transition_type)) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SegmentID segment_id = 0; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(transition_type); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Are we at the beginning of a new segment? 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that navigating to an existing entry (with back/forward) reuses the 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same transition type. We are not adding it as a new segment in that case 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because if this was the target of a redirect, we might end up with 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2 entries for the same final URL. Ex: User types google.net, gets 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirected to google.com. A segment is created for google.net. On 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // google.com users navigates through a link, then press back. That last 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation is for the entry google.com transition typed. We end up adding 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a segment for that one as well. So we end up with google.net and google.com 33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // in the segment table, showing as 2 entries in the NTP. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note also that we should still be updating the visit count for that segment 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which we are not doing now. It should be addressed when 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/96860 is fixed. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((t == content::PAGE_TRANSITION_TYPED || 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t == content::PAGE_TRANSITION_AUTO_BOOKMARK) && 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (transition_type & content::PAGE_TRANSITION_FORWARD_BACK) == 0) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If so, create or get the segment. 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string segment_name = db_->ComputeSegmentName(url); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch segment_id = db_->GetSegmentNamed(segment_name); 352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!segment_id) { 353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch segment_id = db_->CreateSegment(url_id, segment_name); 354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!segment_id) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: if we update an existing segment, we update the url used to 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // represent that segment in order to minimize stale most visited 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // images. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateSegmentRepresentationURL(segment_id, url_id); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: it is possible there is no segment ID set for this visit chain. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This can happen if the initial navigation wasn't AUTO_BOOKMARK or 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TYPED. (For example GENERATED). In this case this visit doesn't count 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // toward any segment. 369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch segment_id = GetLastSegmentID(from_visit); 370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!segment_id) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the segment in the visit. 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->SetSegmentID(visit_id, segment_id)) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally, increase the counter for that segment / day. 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->IncreaseSegmentVisitCount(segment_id, ts, 1)) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return segment_id; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void HistoryBackend::UpdateWithPageEndTime(ContextID context_id, 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 page_id, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_ts) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be filled with the URL ID and the visit ID of the last addition. 393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) VisitID visit_id = tracker_.GetLastVisit(context_id, page_id, url); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(visit_id, end_ts); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateVisitDuration(VisitID visit_id, const Time end_ts) { 398b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the starting visit_time for visit_id. 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_row; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetRowForVisit(visit_id, &visit_row)) { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should never have a negative duration time even when time is skewed. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.visit_duration = end_ts > visit_row.visit_time ? 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_ts - visit_row.visit_time : TimeDelta::FromMicroseconds(0); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateVisitRow(visit_row); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPage(const HistoryAddPageArgs& request) { 412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be filled with the URL ID and the visit ID of the last addition. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<URLID, VisitID> last_ids(0, tracker_.GetLastVisit( 417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) request.context_id, request.page_id, request.referrer)); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID from_visit_id = last_ids.second; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a redirect chain is given, we expect the last item in that chain to be 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the final URL. 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request.redirects.empty() || 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects.back() == request.url); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is adding older history, we need to make sure our times 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are correct. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.time < first_recorded_time_) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = request.time; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition request_transition = request.transition; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition stripped_transition = 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(request_transition); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_keyword_generated = 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition == content::PAGE_TRANSITION_KEYWORD_GENERATED); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is navigating to a not-previously-typed intranet hostname, 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change the transition to TYPED so that the omnibox will learn that this is 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a known host. 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_redirects = request.redirects.size() > 1; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionIsMainFrame(request_transition) && 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition != content::PAGE_TRANSITION_TYPED) && 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_keyword_generated) { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& origin_url(has_redirects ? 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects[0] : request.url); 446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (origin_url.SchemeIs(url::kHttpScheme) || 447010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) origin_url.SchemeIs(url::kHttpsScheme) || 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) origin_url.SchemeIs(url::kFtpScheme)) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host(origin_url.host()); 450a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) size_t registry_length = 451a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::GetRegistryLength( 452a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) host, 453a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, 454a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); 455a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (registry_length == 0 && !db_->IsTypedHost(host)) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition = content::PAGE_TRANSITION_TYPED; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition = 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition | 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionGetQualifier(request_transition)); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_redirects) { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The single entry is both a chain start and end. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = content::PageTransitionFromInt( 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition | 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect case (one element means just the page itself). 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids = AddPageVisit(request.url, request.time, 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids.second, t, request.visit_source); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the segment for this visit. KEYWORD_GENERATED visits should not 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // result in changing most visited, so we don't update segments (most 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visited db). 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_keyword_generated) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateSegments(request.url, from_visit_id, last_ids.second, t, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.time); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the referrer's duration. 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(from_visit_id, request.time); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirect case. Add the redirect chain. 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition redirect_info = 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects = request.redirects; 493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (redirects[0].SchemeIs(url::kAboutScheme)) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the redirect source + referrer is "about" we skip it. This 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happens when a page opens a new frame/window to about:blank and then 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // script sets the URL to somewhere else (used to hide the referrer). It 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // would be nice to keep all these redirects properly but we don't ever 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // see the initial about:blank load, so we don't know where the 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subsequent client redirect came from. 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this case, we just don't bother hooking up the source of the 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirects, so we remove it. 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects.erase(redirects.begin()); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (request_transition & content::PAGE_TRANSITION_CLIENT_REDIRECT) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_info = content::PAGE_TRANSITION_CLIENT_REDIRECT; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The first entry in the redirect chain initiated a client redirect. 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't add this to the database since the referrer is already 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there, so we skip over it but change the transition type of the first 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transition to client redirect. 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The referrer is invalid when restoring a session that features an 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // https tab that redirects to a different host or to http. In this 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case we don't need to reconnect the new redirect with the existing 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chain. 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.referrer.is_valid()) { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request.referrer == redirects[0]); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects.erase(redirects.begin()); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the navigation entry for this visit has replaced that for the 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first visit, remove the CHAIN_END marker from the first visit. This 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can be called a lot, for example, the page cycler, and most of the 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time we won't have changed anything. 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_row; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.did_replace_entry && 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetRowForVisit(last_ids.second, &visit_row) && 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition & content::PAGE_TRANSITION_CHAIN_END) { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition = content::PageTransitionFromInt( 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition & ~content::PAGE_TRANSITION_CHAIN_END); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateVisitRow(visit_row); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t redirect_index = 0; redirect_index < redirects.size(); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_index++) { 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt(stripped_transition | redirect_info); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is the last transition, add a CHAIN_END marker 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirect_index == (redirects.size() - 1)) { 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t = content::PageTransitionFromInt( 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t | content::PAGE_TRANSITION_CHAIN_END); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record all redirect visits with the same timestamp. We don't display 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them anyway, and if we ever decide to, we can reconstruct their order 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the redirect chain. 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids = AddPageVisit(redirects[redirect_index], 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.time, last_ids.second, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t, request.visit_source); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (t & content::PAGE_TRANSITION_CHAIN_START) { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the segment for this visit. 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateSegments(redirects[redirect_index], 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_visit_id, last_ids.second, t, request.time); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the visit_details for this visit. 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(from_visit_id, request.time); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subsequent transitions in the redirect list must all be server 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirects. 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_info = content::PAGE_TRANSITION_SERVER_REDIRECT; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Last, save this redirect chain for later so we can set titles & favicons 566bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // on the redirected pages properly. 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recent_redirects_.Put(request.url, redirects); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the last visit to the tracker so we can get outgoing transitions. 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(evanm): Due to http://b/1194536 we lose the referrers of a subframe 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation anyway, so last_visit_id is always zero for them. But adding 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them here confuses main frame history, so we skip them for now. 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stripped_transition != content::PAGE_TRANSITION_AUTO_SUBFRAME && 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition != content::PAGE_TRANSITION_MANUAL_SUBFRAME && 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_keyword_generated) { 580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tracker_.AddVisit(request.context_id, request.page_id, request.url, 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids.second); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::InitImpl(const std::string& languages) { 588b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!db_) << "Initializing HistoryBackend twice"; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the rare case where the db fails to initialize a dialog may get shown 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the blocks the caller, yet allows other messages through. For this reason 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we only set db_ to the created database if creation is successful. That 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // way other methods won't do anything as db_ is still NULL. 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 596bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Compute the file names. 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath history_name = history_dir_.Append(chrome::kHistoryFilename); 5983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::FilePath thumbnail_name = GetFaviconsFileName(); 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath archived_name = GetArchivedFileName(); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 601bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Delete the old index database files which are no longer used. 602bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch DeleteFTSIndexDatabases(); 603bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // History database. 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(new HistoryDatabase()); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Unretained to avoid a ref loop with db_. 6087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) db_->set_error_callback( 6097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::DatabaseErrorCallback, 6107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Unretained(this))); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sql::InitStatus status = db_->Init(history_name); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case sql::INIT_OK: 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case sql::INIT_FAILURE: { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A NULL db_ will cause all calls on this object to notice this error 6187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // and to not continue. If the error callback scheduled killing the 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database, the task it posted has not executed yet. Try killing the 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database now before we close it. 6217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool kill_db = scheduled_kill_db_; 6227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (kill_db) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KillHistoryDatabase(); 6247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.AttemptedToFixProfileError", kill_db); 625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->NotifyProfileError(status); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill the in-memory database and send it back to the history service on the 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main thread. 635a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 636a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<InMemoryHistoryBackend> mem_backend(new InMemoryHistoryBackend); 637116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (mem_backend->Init(history_name)) 638a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->SetInMemoryBackend(mem_backend.Pass()); 639a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginExclusiveMode(); // Must be after the mem backend read the data. 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Thumbnail database. 6433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(shess): "thumbnail database" these days only stores 6443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // favicons. Thumbnails are stored in "top sites". Consider 6453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // renaming "thumbnail" references to "favicons" or something of the 6463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // sort. 647116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch thumbnail_db_.reset(new ThumbnailDatabase(history_client_)); 6484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (thumbnail_db_->Init(thumbnail_name) != sql::INIT_OK) { 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unlike the main database, we don't error out when the database is too 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new because this error is much less severe. Generally, this shouldn't 65158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // happen since the thumbnail and main database versions should be in sync. 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'll just continue without thumbnails & favicons in this case or any 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other error. 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the thumbnail database."; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Nuke any files corresponding to the legacy Archived History Database, which 65946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // previously retained expired (> 3 months old) history entries, but, in the 66046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // end, was not used for much, and consequently has been removed as of M37. 66146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(engedy): Remove this code after the end of 2014. 66246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) sql::Connection::Delete(archived_name); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Generate the history and thumbnail database metrics only after performing 6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any migration work. 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::RandInt(1, 100) == 50) { 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Only do this computation sometimes since it can be expensive. 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->ComputeDatabaseMetrics(history_name); 6692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (thumbnail_db_) 6702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch thumbnail_db_->ComputeDatabaseMetrics(); 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 67346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) expirer_.SetDatabases(db_.get(), 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(); 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the first item in our database. 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start expiring old stuff. 68446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) expirer_.StartExpiringOldStuff(TimeDelta::FromDays(kExpireDaysThreshold)); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 687b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 68846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) android_provider_backend_.reset( 68946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new AndroidProviderBackend(GetAndroidCacheFileName(), 69046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) db_.get(), 69146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) thumbnail_db_.get(), 69246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) history_client_, 69346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) delegate_.get())); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HISTOGRAM_TIMES("History.InitTime", 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 701ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid HistoryBackend::OnMemoryPressure( 702ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool trim_aggressively = memory_pressure_level == 704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL; 705ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (db_) 706ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db_->TrimMemory(trim_aggressively); 707ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (thumbnail_db_) 708ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch thumbnail_db_->TrimMemory(trim_aggressively); 709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 710ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloseAllDatabases() { 712b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Commit the long-running transaction. 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 71658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Forget the first recorded time since the database is closed. 71758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) first_recorded_time_ = base::Time(); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 719b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::pair<URLID, VisitID> HistoryBackend::AddPageVisit( 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time time, 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID referring_visit, 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition, 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Top-level frame navigations are visible, everything else is hidden 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool new_hidden = !content::PageTransitionIsMainFrame(transition); 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: This code must stay in sync with 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExpireHistoryBackend::ExpireURLsForVisits(). 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkasting): http://b/1148304 We shouldn't be marking so many URLs as 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typed, which would eliminate the need for this code. 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int typed_increment = 0; 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition_type = 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(transition); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((transition_type == content::PAGE_TRANSITION_TYPED && 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !content::PageTransitionIsRedirect(transition)) || 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition_type == content::PAGE_TRANSITION_KEYWORD_GENERATED) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typed_increment = 1; 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Only count the page visit if it came from user browsing and only count it 748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // once when cycling through a redirect chain. 749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (visit_source == SOURCE_BROWSED && 750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (transition & content::PAGE_TRANSITION_CHAIN_END) != 0) { 751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RecordTopPageVisitStats(url); 752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if this URL is already in the DB. 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update of an existing row. 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionStripQualifier(transition) != 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_RELOAD) 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(url_info.visit_count() + 1); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typed_increment) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(url_info.typed_count() + typed_increment); 765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (url_info.last_visit() < time) 766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_info.set_last_visit(time); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only allow un-hiding of pages, never hiding. 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_hidden) 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(url_id, url_info); 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Addition of a new row. 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(1); 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(typed_increment); 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(time); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(new_hidden); 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_id = db_->AddURL(url_info); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding URL failed."; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(0, 0); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.id_ = url_id; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the visit with the time to the database. 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, time, referring_visit, transition, 0); 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = db_->AddVisit(&visit_info, visit_source); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification of the visit. 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_id) { 798b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 799b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlVisited(transition, &url_info); 800b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 801a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<URLVisitedDetails> details(new URLVisitedDetails); 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->transition = transition; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->row = url_info; 804cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) details->visit_time = time; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(meelapshah) Disabled due to potential PageCycler regression. 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-enable this. 807116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // QueryRedirectsTo(url, &details->redirects); 808a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URL_VISITED, 809a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to build visit insert statement: " 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "url_id = " << url_id; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(url_id, visit_id); 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPagesWithDetails(const URLRows& urls, 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 820b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> modified(new URLsModifiedDetails); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = urls.begin(); i != urls.end(); ++i) { 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!i->last_visit().is_null()); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 82746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // As of M37, we no longer maintain an archived database, ignore old visits. 82846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (IsExpiredVisitTime(i->last_visit())) 82946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow existing_url; 83246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLID url_id = db_->GetRowForURL(i->url(), &existing_url); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the page if it doesn't exist. 83546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) url_id = db_->AddURL(*i); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Could not add row to DB"; 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 841f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) modified->changed_urls.push_back(*i); 842f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) modified->changed_urls.back().set_id(url_id); // i->id_ is likely 0. 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sync code manages the visits itself. 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_source != SOURCE_SYNCED) { 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make up a visit to correspond to the last visit to the page. 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, i->last_visit(), 0, 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_LINK | 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END), 0); 85346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!db_->AddVisit(&visit_info, visit_source)) { 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding visit failed."; 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 86446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (typed_url_syncable_service_.get()) 865b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&modified->changed_urls); 866b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification for typed URLs that have been modified. This 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be picked up by the in-memory URL database on the main thread. 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 873a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) modified.PassAs<HistoryDetails>()); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) { 87946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return time < expirer_.GetCurrentExpirationTime(); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 882a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HistoryBackend::SetPageTitle(const GURL& url, 883a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 884b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search for recent redirects which should get the same title. We make a 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dummy list containing the exact URL visited if there are no redirects so 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the processing below can be the same. 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList dummy_list; 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects; 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(url); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &iter->second; 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This redirect chain should have the destination URL as the last item. 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirects->empty()); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirects->back() == url); 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect chain stored, make up one containing the URL we want so we 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can use the same logic below. 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dummy_list.push_back(url); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &dummy_list; 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> details(new URLsModifiedDetails); 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirects->size(); i++) { 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID row_id = db_->GetRowForURL(redirects->at(i), &row); 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row_id && row.title() != title) { 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_title(title); 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(row_id, row); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->changed_urls.push_back(row); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast notifications for any URLs that have changed. This will 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the in-memory database and the InMemoryURLIndex. 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!details->changed_urls.empty()) { 920b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 921b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&details->changed_urls); 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 923a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPageNoVisitForBookmark(const GURL& url, 929a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 930b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is already known, nothing to do. 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!title.empty()) { 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_title(title); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url_info.set_title(base::UTF8ToUTF16(url.spec())); 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(Time::Now()); 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the page hidden. If the user types it in, it'll unhide. 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(true); 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::IterateURLs( 95490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const scoped_refptr<visitedlink::VisitedLinkDelegate::URLEnumerator>& 9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator) { 956b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase::URLEnumerator e; 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->InitURLEnumeratorForEverything(&e)) { 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (e.GetNextURL(&info)) { 9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator->OnURL(info.url()); 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(true); // Success. 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(false); // Failure. 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetAllTypedURLs(URLRows* urls) { 971b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetAllTypedUrls(urls); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsForURL(URLID id, VisitVector* visits) { 977b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetVisitsForURL(id, visits); 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentVisitsForURL(URLID id, 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits, 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 985b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetMostRecentVisitsForURL(id, max_visits, visits); 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 990116680a4aac90f2aa7413d9095a592090648e557Ben Murdochsize_t HistoryBackend::UpdateURLs(const history::URLRows& urls) { 991116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!db_) 992116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return 0; 993116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 994116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<URLsModifiedDetails> details(new URLsModifiedDetails); 995116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (history::URLRows::const_iterator it = urls.begin(); it != urls.end(); 996116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++it) { 997116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(it->id()); 998116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (db_->UpdateURLRow(it->id(), *it)) 999116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch details->changed_urls.push_back(*it); 1000116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1001116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1002116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Broadcast notifications for any URLs that have actually been changed. This 1003116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // will update the in-memory database and the InMemoryURLIndex. 1004116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t num_updated_records = details->changed_urls.size(); 1005116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (num_updated_records) { 1006116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (typed_url_syncable_service_) 1007116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch typed_url_syncable_service_->OnUrlsModified(&details->changed_urls); 1008116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 1009116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch details.PassAs<HistoryDetails>()); 1010116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScheduleCommit(); 1011116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1012116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return num_updated_records; 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::AddVisits(const GURL& url, 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<VisitInfo>& visits, 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 1018b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<VisitInfo>::const_iterator visit = visits.begin(); 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit != visits.end(); ++visit) { 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddPageVisit( 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, visit->first, 0, visit->second, visit_source).first) { 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::RemoveVisits(const VisitVector& visits) { 1033b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.ExpireVisits(visits); 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsSource(const VisitVector& visits, 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSourceMap* sources) { 1043b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsSource(visits, sources); 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetURL(const GURL& url, history::URLRow* url_row) { 1051b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetRowForURL(url, url_row) != 0; 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1056116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HistoryBackend::QueryURL(const GURL& url, 1057116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool want_visits, 1058116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueryURLResult* result) { 1059116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(result); 1060116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result->success = db_ && db_->GetRowForURL(url, &result->row); 1061f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Optionally query the visits. 1062116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (result->success && want_visits) 1063116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch db_->GetVisitsForURL(result->row.id(), &result->visits); 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1066b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TypedUrlSyncableService* HistoryBackend::GetTypedUrlSyncableService() const { 1067b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return typed_url_syncable_service_.get(); 1068b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 1069b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keyword visits -------------------------------------------------------------- 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetKeywordSearchTermsForURL(const GURL& url, 1073116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch KeywordID keyword_id, 1074a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& term) { 1075b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the ID for this URL. 10790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch URLRow row; 10800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!db_->GetRowForURL(url, &row)) { 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a small possibility the url was deleted before the keyword 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was added. Ignore the request. 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch db_->SetKeywordSearchTermsForURL(row.id(), keyword_id, term); 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications( 10890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, 1090a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<HistoryDetails>( 10910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new KeywordSearchUpdatedDetails(row, keyword_id, term))); 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HistoryBackend::DeleteAllSearchTermsForKeyword(KeywordID keyword_id) { 1096b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteAllSearchTermsForKeyword(keyword_id); 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void HistoryBackend::DeleteKeywordSearchTermForURL(const GURL& url) { 11040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!db_) 11050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 11060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 11080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!url_id) 11090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 11100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) db_->DeleteKeywordSearchTermForURL(url_id); 11110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 11120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BroadcastNotifications( 11130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, 11140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_ptr<HistoryDetails>(new KeywordSearchDeletedDetails(url_id))); 11150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScheduleCommit(); 11160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 11170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1118116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HistoryBackend::DeleteMatchingURLsForKeyword(KeywordID keyword_id, 11195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& term) { 11205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!db_) 11215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 11225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<KeywordSearchTermRow> rows; 11245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (db_->GetKeywordSearchTermRows(term, &rows)) { 11255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<GURL> items_to_delete; 11265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLRow row; 11275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (std::vector<KeywordSearchTermRow>::iterator it = rows.begin(); 11285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != rows.end(); ++it) { 11295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((it->keyword_id == keyword_id) && db_->GetURLRow(it->url_id, &row)) 11305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) items_to_delete.push_back(row.url()); 11315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeleteURLs(items_to_delete); 11335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 11355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Downloads ------------------------------------------------------------------- 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)uint32 HistoryBackend::GetNextDownloadId() { 1139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return db_ ? db_->GetNextDownloadId() : content::DownloadItem::kInvalidId; 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get all the download entries from the database. 11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::QueryDownloads(std::vector<DownloadRow>* rows) { 1144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->QueryDownloads(rows); 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Update a particular download entry. 11492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::UpdateDownload(const history::DownloadRow& data) { 1150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->UpdateDownload(data); 11532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool HistoryBackend::CreateDownload(const history::DownloadRow& history_info) { 1157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 1158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 1159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool success = db_->CreateDownload(history_info); 11602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 1161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return success; 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HistoryBackend::RemoveDownloads(const std::set<uint32>& ids) { 1165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_before = db_->CountDownloads(); 11682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks started_removing = base::TimeTicks::Now(); 11692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HistoryBackend uses a long-running Transaction that is committed 11702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // periodically, so this loop doesn't actually hit the disk too hard. 11717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (std::set<uint32>::const_iterator it = ids.begin(); 11727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch it != ids.end(); ++it) { 11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->RemoveDownload(*it); 11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScheduleCommit(); 11762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks finished_removing = base::TimeTicks::Now(); 11777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_after = db_->CountDownloads(); 11787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 11797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_LE(downloads_count_after, downloads_count_before); 11807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (downloads_count_after > downloads_count_before) 11817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 11827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t num_downloads_deleted = downloads_count_before - downloads_count_after; 11837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCount", 11847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch num_downloads_deleted); 11857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::TimeDelta micros = (1000 * (finished_removing - started_removing)); 11867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTime", micros); 11877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (num_downloads_deleted > 0) { 11887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTimePerRecord", 11897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (1000 * micros) / num_downloads_deleted); 11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_GE(ids.size(), num_downloads_deleted); 11927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ids.size() < num_downloads_deleted) 11937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 11947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCountNotRemoved", 11957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ids.size() - num_downloads_deleted); 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1198116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HistoryBackend::QueryHistory(const base::string16& text_query, 1199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const QueryOptions& options, 1200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueryResults* query_results) { 1201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(query_results); 1202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeTicks beginning_time = base::TimeTicks::Now(); 1203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text_query.empty()) { 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Basic history query for the main database. 1206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueryHistoryBasic(options, query_results); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Text history query. 1209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueryHistoryText(text_query, options, query_results); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.QueryHistory", 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic time-based querying of history. 121746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void HistoryBackend::QueryHistoryBasic(const QueryOptions& options, 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryResults* result) { 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First get all visits. 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 122146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool has_more_results = db_->GetVisibleVisitsInRange(options, &visits); 12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount()); 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now add them and the URL rows to the results. 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLResult url_result; 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); i++) { 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VisitRow visit = visits[i]; 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a result row for this visit, get the URL info from the DB. 123046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!db_->GetURLRow(visit.url_id, &url_result)) { 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to get id " << visit.url_id 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " from history.urls."; 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // DB out of sync and URL doesn't exist, try to recover. 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_result.url().is_valid()) { 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Got invalid URL from history.urls with id " 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << visit.url_id << ": " 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << url_result.url().possibly_invalid_spec(); 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Don't report invalid URLs in case of corruption. 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_result.set_visit_time(visit.visit_time); 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set whether the visit was blocked for a managed user by looking at the 1246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // transition type. 1247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_result.set_blocked_visit( 1248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0); 1249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't set any of the query-specific parts of the URLResult, since 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // snippets and stuff don't apply to basic querying. 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->AppendURLBySwapping(&url_result); 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_more_results && options.begin_time <= first_recorded_time_) 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->set_reached_beginning(true); 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Text-based querying of history. 126046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void HistoryBackend::QueryHistoryText(const base::string16& text_query, 1261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const QueryOptions& options, 1262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryResults* result) { 1263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLRows text_matches; 126446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) db_->GetTextMatches(text_query, &text_matches); 1265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<URLResult> matching_visits; 1267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitVector visits; // Declare outside loop to prevent re-construction. 1268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < text_matches.size(); i++) { 1269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const URLRow& text_match = text_matches[i]; 1270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get all visits for given URL match. 127146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) db_->GetVisibleVisitsForURL(text_match.id(), options, &visits); 1272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < visits.size(); j++) { 1273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult url_result(text_match); 1274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_result.set_visit_time(visits[j].visit_time); 1275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch matching_visits.push_back(url_result); 1276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::sort(matching_visits.begin(), matching_visits.end(), 1280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult::CompareVisitTime); 1281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t max_results = options.max_count == 0 ? 1283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::numeric_limits<size_t>::max() : static_cast<int>(options.max_count); 1284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (std::vector<URLResult>::iterator it = matching_visits.begin(); 1285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it != matching_visits.end() && result->size() < max_results; ++it) { 1286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->AppendURLBySwapping(&(*it)); 1287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (matching_visits.size() == result->size() && 1290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options.begin_time <= first_recorded_time_) 1291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->set_reached_beginning(true); 1292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1294116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HistoryBackend::QueryRedirectsFrom(const GURL& from_url, 1295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RedirectList* redirects) { 1296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch redirects->clear(); 1297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!db_) 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLID from_url_id = db_->GetRowForURL(from_url, NULL); 1301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VisitID cur_visit = db_->GetMostRecentVisitForURL(from_url_id, NULL); 1302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!cur_visit) 1303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; // No visits for URL. 1304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetRedirectsFromSpecificVisit(cur_visit, redirects); 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1308116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HistoryBackend::QueryRedirectsTo(const GURL& to_url, 1309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RedirectList* redirects) { 1310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch redirects->clear(); 1311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!db_) 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch URLID to_url_id = db_->GetRowForURL(to_url, NULL); 1315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VisitID cur_visit = db_->GetMostRecentVisitForURL(to_url_id, NULL); 1316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!cur_visit) 1317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; // No visits for URL. 1318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetRedirectsToSpecificVisit(cur_visit, redirects); 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetVisibleVisitCountToHost( 1323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const GURL& url, 1324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VisibleVisitCountToHostResult* result) { 1325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result->count = 0; 1326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result->success = db_.get() && 1327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch db_->GetVisibleVisitCountToHost( 1328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch url, &result->count, &result->first_visit); 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1331116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HistoryBackend::QueryMostVisitedURLs(int result_count, 1332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int days_back, 1333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MostVisitedURLList* result) { 1334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!db_) 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 1338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch db_->QuerySegmentUsage( 1339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Time::Now() - base::TimeDelta::FromDays(days_back), 1340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result_count, 1341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &data.get()); 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 1344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PageUsageData* current_data = data[i]; 1345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RedirectList redirects; 1346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueryRedirectsFrom(current_data->GetURL(), &redirects); 1347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MostVisitedURL url = MakeMostVisitedURL(*current_data, redirects); 1348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result->push_back(url); 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1352116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HistoryBackend::QueryFilteredURLs(int result_count, 1353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const history::VisitFilter& filter, 1354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool extended_info, 1355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch history::FilteredURLList* result) { 1356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(result); 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time request_start = base::Time::Now(); 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result->clear(); 1360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetDirectVisitsDuringTimes(filter, 0, &visits); 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, double> score_map; 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score_map[visits[i].url_id] += filter.GetVisitScore(visits[i]); 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(georgey): experiment with visit_segment database granularity (it is 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // currently 24 hours) to use it directly instead of using visits database, 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which is considerably slower. 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.reserve(score_map.size()); 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<URLID, double>::iterator it = score_map.begin(); 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != score_map.end(); ++it) { 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* pud = new PageUsageData(it->first); 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pud->SetScore(it->second); 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.push_back(pud); 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Limit to the top |result_count| results. 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(data.begin(), data.end(), PageUsageData::Predicate); 13872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result_count && implicit_cast<int>(data.size()) > result_count) 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.resize(result_count); 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetURLRow(data[i]->GetID(), &info)) { 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetURL(info.url()); 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetTitle(info.title()); 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURL url(*current_data); 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extended_info) { 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(current_data->GetID(), &visits); 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.size() > 0) { 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.total_visits = visits.size(); 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.duration_opened += 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits[i].visit_duration.InSeconds(); 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits[i].visit_time > url.extended_info.last_visit_time) { 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.last_visit_time = visits[i].visit_time; 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(macourteau): implement the url.extended_info.visits stat. 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result->push_back(url); 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delta_time = std::max(1, std::min(999, 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>((base::Time::Now() - request_start).InMilliseconds()))); 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATIC_HISTOGRAM_POINTER_BLOCK( 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NewTabPage.SuggestedSitesLoadTime", 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(delta_time), 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LinearHistogram::FactoryGet("NewTabPage.SuggestedSitesLoadTime", 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1000, 100, base::Histogram::kUmaTargetedHistogramFlag)); 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsFromSpecificVisit( 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, history::RedirectList* redirects) { 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow any redirects from the given visit and add them to the list. 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It *should* be impossible to get a circular chain here, but we check 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just in case to avoid infinite loops. 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectFromVisit(cur_visit, &cur_visit, &cur_url)) { 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsToSpecificVisit( 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow redirects going to cur_visit. These are added to |redirects| in 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the order they are found. If a redirect chain looks like A -> B -> C and 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |cur_visit| = C, redirects will be {B, A} in that order. 1453b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectToVisit(cur_visit, &cur_visit, &cur_url)) { 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1469116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid HistoryBackend::ScheduleAutocomplete(const base::Callback< 1470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void(history::HistoryBackend*, history::URLDatabase*)>& callback) { 1471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback.Run(this, db_.get()); 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1474bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid HistoryBackend::DeleteFTSIndexDatabases() { 1475bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Find files on disk matching the text databases file pattern so we can 1476bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // quickly test for and delete them. 1477bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath::StringType filepattern = 1478bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch FILE_PATH_LITERAL("History Index *"); 1479bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FileEnumerator enumerator( 1480bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch history_dir_, false, base::FileEnumerator::FILES, filepattern); 1481bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch int num_databases_deleted = 0; 1482bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath current_file; 1483bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch while (!(current_file = enumerator.Next()).empty()) { 1484bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (sql::Connection::Delete(current_file)) 1485bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted++; 1486bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 1487bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch UMA_HISTOGRAM_COUNTS("History.DeleteFTSIndexDatabases", 1488bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted); 1489bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 1490bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFavicons( 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 14946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<int>& desired_sizes, 1495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 14966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(NULL, icon_urls, icon_types, desired_sizes, 14972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void HistoryBackend::GetLargestFaviconForURL( 15010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const GURL& page_url, 15020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<int>& icon_types, 15030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int minimum_size_in_pixels, 1504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult* favicon_bitmap_result) { 15058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(favicon_bitmap_result); 15068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!db_ || !thumbnail_db_) 15088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 15098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 15118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 15138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings) || 15148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) icon_mappings.empty()) 15158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 15168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int required_icon_types = 0; 15188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<int>::const_iterator i = icon_types.begin(); 15198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) i != icon_types.end(); ++i) { 15208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) required_icon_types |= *i; 15218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find the largest bitmap for each IconType placing in 15248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // |largest_favicon_bitmaps|. 15250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::map<favicon_base::IconType, FaviconBitmap> largest_favicon_bitmaps; 15268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<IconMapping>::const_iterator i = icon_mappings.begin(); 15278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) i != icon_mappings.end(); ++i) { 15288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!(i->icon_type & required_icon_types)) 15298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) continue; 15308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 15318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(i->icon_id, &bitmap_id_sizes); 15328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FaviconBitmap& largest = largest_favicon_bitmaps[i->icon_type]; 15338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<FaviconBitmapIDSize>::const_iterator j = 15348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_id_sizes.begin(); j != bitmap_id_sizes.end(); ++j) { 15358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest.bitmap_id == 0 || 15368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest.pixel_size.width() < j->pixel_size.width() && 15378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.pixel_size.height() < j->pixel_size.height())) { 15388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.icon_id = i->icon_id; 15398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.bitmap_id = j->bitmap_id; 15408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest.pixel_size = j->pixel_size; 15418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest_favicon_bitmaps.empty()) 15458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 15468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Find an icon which is larger than minimum_size_in_pixels in the order of 15488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // icon_types. 15498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FaviconBitmap largest_icon; 15508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<int>::const_iterator t = icon_types.begin(); 15518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) t != icon_types.end(); ++t) { 15520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (std::map<favicon_base::IconType, FaviconBitmap>::const_iterator f = 15530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch largest_favicon_bitmaps.begin(); 15540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch f != largest_favicon_bitmaps.end(); 15550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++f) { 15568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (f->first & *t && 15578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest_icon.bitmap_id == 0 || 15588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) (largest_icon.pixel_size.height() < f->second.pixel_size.height() && 15598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon.pixel_size.width() < f->second.pixel_size.width()))) { 15608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon = f->second; 15618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (largest_icon.pixel_size.width() > minimum_size_in_pixels && 15648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) largest_icon.pixel_size.height() > minimum_size_in_pixels) 15658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) break; 15668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) GURL icon_url; 15690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type; 15708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(largest_icon.icon_id, &icon_url, 15718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &icon_type)) { 15728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 15738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::Time last_updated; 1576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult bitmap_result; 15778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.icon_url = icon_url; 15788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.icon_type = icon_type; 15798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(largest_icon.bitmap_id, 15808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &last_updated, 15818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &bitmap_result.bitmap_data, 15828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &bitmap_result.pixel_size)) { 15838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 15848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 15858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 15878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 15888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (bitmap_result.is_valid()) 15898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) *favicon_bitmap_result = bitmap_result; 15908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) HISTOGRAM_TIMES("History.GetLargestFaviconForURL", 15928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) TimeTicks::Now() - beginning_time); 15938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 15948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFaviconsForURL( 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 15986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<int>& desired_sizes, 1599f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 16002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(bitmap_results); 16016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) GetFaviconsFromDB(page_url, icon_types, desired_sizes, bitmap_results); 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::GetFaviconForID( 16050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id, 16066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int desired_size, 1607f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 16080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 16106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::vector<int> desired_sizes; 16116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) desired_sizes.push_back(desired_size); 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get results from DB. 16142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, 16156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) desired_sizes, 16162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetch( 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 16236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<int>& desired_sizes, 1624f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 16252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(&page_url, icon_urls, icon_types, 16266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) desired_sizes, bitmap_results); 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::MergeFavicon( 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 16312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 16320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedMemory> bitmap_data, 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& pixel_size) { 1635b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id = 163990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_id) { 16422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There is no favicon at |icon_url|, create it. 1643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch favicon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 16442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 16472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(favicon_id, &bitmap_id_sizes); 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is already a favicon bitmap of |pixel_size| at |icon_url|, 16502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // replace it. 16512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool bitmap_identical = false; 16522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool replaced_bitmap = false; 16532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 16542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes[i].pixel_size == pixel_size) { 16552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsFaviconBitmapDataEqual(bitmap_id_sizes[i].bitmap_id, bitmap_data)) { 16562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 16572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id_sizes[i].bitmap_id, base::Time::Now()); 16582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_identical = true; 16592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 16602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id_sizes[i].bitmap_id, 16612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_data, base::Time::Now()); 16622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) replaced_bitmap = true; 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a vector of the pixel sizes of the favicon bitmaps currently at 16692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url|. 16702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size> favicon_sizes; 16712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) 16722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmap_id_sizes[i].pixel_size); 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!replaced_bitmap && !bitmap_identical) { 16752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set the preexisting favicon bitmaps as expired as the preexisting favicon 16762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmaps are not consistent with the merged in data. 16772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(favicon_id); 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete an arbitrary favicon bitmap to avoid going over the limit of 16802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |kMaxFaviconBitmapsPerIconURL|. 16812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes.size() >= kMaxFaviconBitmapsPerIconURL) { 16822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[0].bitmap_id); 16832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.erase(favicon_sizes.begin()); 16842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 16852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, bitmap_data, base::Time::Now(), 16862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pixel_size); 16872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(pixel_size); 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A site may have changed the favicons that it uses for |page_url|. 16912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Example Scenario: 16922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // page_url = news.google.com 169358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Initial State: www.google.com/favicon.ico 16x16, 32x32 16942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // MergeFavicon(news.google.com, news.google.com/news_specific.ico, ..., 16952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ..., 16x16) 16962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 16972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulties: 16982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1. Sync requires that a call to GetFaviconsForURL() returns the 16992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |bitmap_data| passed into MergeFavicon(). 17002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - It is invalid for the 16x16 bitmap for www.google.com/favicon.ico to 17012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stay mapped to news.google.com because it would be unclear which 16x16 17022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap should be returned via GetFaviconsForURL(). 17032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 17042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2. www.google.com/favicon.ico may be mapped to more than just 17052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com (eg www.google.com). 17062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - The 16x16 bitmap cannot be deleted from www.google.com/favicon.ico 17072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 17082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // To resolve these problems, we copy all of the favicon bitmaps previously 17092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // mapped to news.google.com (|page_url|) and add them to the favicon at 17102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com/news_specific.ico (|icon_url|). The favicon sizes for 17112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url| are set to default to indicate that |icon_url| has incomplete 17122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // / incorrect data. 171358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Difficulty 1: All but news.google.com/news_specific.ico are unmapped from 17142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com 17152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulty 2: The favicon bitmaps for www.google.com/favicon.ico are not 17162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // modified. 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 17192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_type, &icon_mappings); 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy the favicon bitmaps mapped to |page_url| to the favicon at |icon_url| 17222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // till the limit of |kMaxFaviconBitmapsPerIconURL| is reached. 17232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) { 17242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 17252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings[i].icon_url == icon_url) 17282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmap> bitmaps_to_copy; 17312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmaps(icon_mappings[i].icon_id, 17322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &bitmaps_to_copy); 17332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t j = 0; j < bitmaps_to_copy.size(); ++j) { 17342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do not add a favicon bitmap at a pixel size for which there is already 17352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a favicon bitmap mapped to |icon_url|. The one there is more correct 17362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and having multiple equally sized favicon bitmaps for |page_url| is 17372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ambiguous in terms of GetFaviconsForURL(). 17382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(), 17392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.end(), bitmaps_to_copy[j].pixel_size); 17402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != favicon_sizes.end()) 17412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 17422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add the favicon bitmap as expired as it is not consistent with the 17442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // merged in data. 17452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, 17462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].bitmap_data, base::Time(), 17472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].pixel_size); 17482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmaps_to_copy[j].pixel_size); 17492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 17512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 17522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 17532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 17542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update the favicon mappings such that only |icon_url| is mapped to 17562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |page_url|. 17572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool mapping_changed = false; 17582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings.size() != 1 || icon_mappings[0].icon_url != icon_url) { 17590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 17602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_ids.push_back(favicon_id); 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, favicon_ids); 17622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mapping_changed = true; 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mapping_changed || !bitmap_identical) 17662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFavicons( 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 1773f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapData>& 1774f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_bitmap_data) { 1775b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(ValidateSetFaviconsParams(favicon_bitmap_data)); 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1780f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Build map of FaviconRawBitmapData for each icon url. 1781f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) typedef std::map<GURL, std::vector<favicon_base::FaviconRawBitmapData> > 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL; 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL grouped_by_icon_url; 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) grouped_by_icon_url[icon_url].push_back(favicon_bitmap_data[i]); 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Track whether the method modifies or creates any favicon bitmaps, favicons 17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // or icon mappings. 17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool data_modified = false; 17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> icon_ids; 17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapDataByIconURL::const_iterator it = grouped_by_icon_url.begin(); 17952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != grouped_by_icon_url.end(); ++it) { 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = it->first; 17970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID icon_id = 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!icon_id) { 18012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(pkotwicz): Remove the favicon sizes attribute from 18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ThumbnailDatabase::AddFavicon(). 1803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 18042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified = true; 18052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_ids.push_back(icon_id); 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data_modified) 18092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, &data_modified); 18102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 18112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, NULL); 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified |= 18152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids); 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data_modified) { 18182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send notification to the UI as an icon mapping, favicon, or favicon 18192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap was changed by this function. 18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 18212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) { 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1828b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !thumbnail_db_->GetIconMappingsForPageURL(page_url, 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings)) 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(m->icon_id); 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloneFavicons(const GURL& old_page_url, 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& new_page_url) { 1842b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent cross-domain cloning. 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetImportedFavicons( 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ImportedFaviconUsage>& favicon_usage) { 1855b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time now = Time::Now(); 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Track all URLs that had their favicons set or updated. 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<GURL> favicons_changed; 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_usage.size(); i++) { 18640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID favicon_id = 18650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch thumbnail_db_->GetFaviconIDForFaviconURL( 18660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_usage[i].favicon_url, favicon_base::FAVICON, NULL); 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_id) { 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This favicon doesn't exist yet, so we create it using the given data. 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Pass in real pixel size. 18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_id = thumbnail_db_->AddFavicon( 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_usage[i].favicon_url, 18720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FAVICON, 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new base::RefCountedBytes(favicon_usage[i].png_data), 18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now, 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size()); 18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the mapping from all the URLs to the favicon. 187946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HistoryClient* history_client = GetHistoryClient(); 18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator url = favicon_usage[i].urls.begin(); 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url != favicon_usage[i].urls.end(); ++url) { 18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*url, &url_row)) { 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL is present as a bookmark, add the url in history to 18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save the favicon mapping. This will match with what history db does 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for regular bookmarked URLs with favicons - when history db is 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cleaned, we keep an entry in the db with 0 visits as long as that 18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // url is bookmarked. 188946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (history_client && history_client->IsBookmarked(*url)) { 18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(*url); 18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(0); 18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(0); 18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(base::Time()); 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 190090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL( 19010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch *url, favicon_base::FAVICON, NULL)) { 19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is present in history, update the favicon *only* if it is not 19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set already. 19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicons_changed.empty()) { 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the notification about the changed favicon URLs. 1913a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<FaviconChangedDetails> changed_details( 1914a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new FaviconChangedDetails); 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.swap(favicons_changed); 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 1917a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) changed_details.PassAs<HistoryDetails>()); 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetchImpl( 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL* page_url, 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 19256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<int>& desired_sizes, 1926f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* bitmap_results) { 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |page_url| is specified, |icon_types| must be either a single icon 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // type or icon types which are equivalent. 19290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!page_url || icon_types == favicon_base::FAVICON || 19300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == favicon_base::TOUCH_ICON || 19310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == favicon_base::TOUCH_PRECOMPOSED_ICON || 19320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch icon_types == 19330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (favicon_base::TOUCH_ICON | favicon_base::TOUCH_PRECOMPOSED_ICON)); 19342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results->clear(); 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1936b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The icon type for which the mappings will the updated and data will be 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned. 19440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType selected_icon_type = favicon_base::INVALID_ICON; 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_urls.size(); ++i) { 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = icon_urls[i]; 19480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type_out; 19490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const favicon_base::FaviconID favicon_id = 195090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL( 195190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_url, icon_types, &icon_type_out); 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_id) { 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return and update icon mappings only for the largest icon type. As 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |icon_urls| is not sorted in terms of icon type, clear |favicon_ids| 19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if an |icon_url| with a larger icon type is found. 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out > selected_icon_type) { 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_icon_type = icon_type_out; 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.clear(); 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out == selected_icon_type) 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_url && !favicon_ids.empty()) { 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_updated = 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(*page_url, selected_icon_type, 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids); 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mappings_updated) { 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(*page_url); 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_sizes, 19776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) bitmap_results); 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconBitmaps( 19810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID icon_id, 1982f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<favicon_base::FaviconRawBitmapData>& favicon_bitmap_data, 19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* favicon_bitmaps_changed) { 19842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 19852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = false; 19862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes); 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1990f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapData> to_add = favicon_bitmap_data; 19912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 19932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& pixel_size = bitmap_id_sizes[i].pixel_size; 1994f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapData>::iterator match_it = 19950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_add.end(); 1996f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (std::vector<favicon_base::FaviconRawBitmapData>::iterator it = 19970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch to_add.begin(); 19980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != to_add.end(); 19990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 20002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->pixel_size == pixel_size) { 20012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) match_it = it; 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id = bitmap_id_sizes[i].bitmap_id; 20072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (match_it == to_add.end()) { 20082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id); 20092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 20112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 20132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed && 20142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !*favicon_bitmaps_changed && 20152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsFaviconBitmapDataEqual(bitmap_id, match_it->bitmap_data)) { 20162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 20172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id, base::Time::Now()); 20182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 20192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id, match_it->bitmap_data, 20202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now()); 20212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 20232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 20242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 20252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) to_add.erase(match_it); 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < to_add.size(); ++i) { 20302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(icon_id, to_add[i].bitmap_data, 20312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now(), to_add[i].pixel_size); 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 20342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool HistoryBackend::ValidateSetFaviconsParams(const std::vector< 2039f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapData>& favicon_bitmap_data) const { 20402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::map<GURL, size_t> BitmapsPerIconURL; 20412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BitmapsPerIconURL num_bitmaps_per_icon_url; 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 2043868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!favicon_bitmap_data[i].bitmap_data.get()) 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 20472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!num_bitmaps_per_icon_url.count(icon_url)) 20482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_bitmaps_per_icon_url[icon_url] = 1u; 20492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 20502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++num_bitmaps_per_icon_url[icon_url]; 20512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 20522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (num_bitmaps_per_icon_url.size() > kMaxFaviconsPerPage) 20542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapsPerIconURL::const_iterator it = num_bitmaps_per_icon_url.begin(); 20572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != num_bitmaps_per_icon_url.end(); ++it) { 20582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->second > kMaxFaviconBitmapsPerIconURL) 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistoryBackend::IsFaviconBitmapDataEqual( 20652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id, 20662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<base::RefCountedMemory>& new_bitmap_data) { 2067868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!new_bitmap_data.get()) 20682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedMemory> original_bitmap_data; 20712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmap(bitmap_id, 20722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 20732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &original_bitmap_data, 20742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL); 20752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_bitmap_data->Equals(original_bitmap_data); 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconsFromDB( 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 20816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<int>& desired_sizes, 2082f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* favicon_bitmap_results) { 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(favicon_bitmap_results); 20842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_bitmap_results->clear(); 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2086b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Time the query. 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get FaviconIDs for |page_url| and one of |icon_types|. 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types, 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings); 20960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> favicon_ids; 20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) 20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(icon_mappings[i].icon_id); 20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populate |favicon_bitmap_results| and |icon_url_sizes|. 21012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = GetFaviconBitmapResultsForBestMatch(favicon_ids, 21026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) desired_sizes, favicon_bitmap_results); 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 21052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success && !favicon_bitmap_results->empty(); 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconBitmapResultsForBestMatch( 21090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& candidate_favicon_ids, 21106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<int>& desired_sizes, 2111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<favicon_base::FaviconRawBitmapResult>* favicon_bitmap_results) { 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->clear(); 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate_favicon_ids.empty()) 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the FaviconID and the FaviconBitmapIDs which best match 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |desired_size_in_dip| and |desired_scale_factors|. 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Select bitmap results from multiple favicons once 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content::FaviconStatus supports multiple icon URLs. 21210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::FaviconID best_favicon_id = 0; 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapID> best_bitmap_ids; 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float highest_score = kSelectFaviconFramesInvalidScore; 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < candidate_favicon_ids.size(); ++i) { 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(candidate_favicon_ids[i], 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_id_sizes); 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build vector of gfx::Size from |bitmap_id_sizes|. 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<gfx::Size> sizes; 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < bitmap_id_sizes.size(); ++j) 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizes.push_back(bitmap_id_sizes[j].pixel_size); 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<size_t> candidate_bitmap_indices; 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score = 0; 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFaviconFrameIndices(sizes, 21376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) desired_sizes, 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &candidate_bitmap_indices, 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &score); 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (score > highest_score) { 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) highest_score = score; 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_favicon_id = candidate_favicon_ids[i], 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.clear(); 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < candidate_bitmap_indices.size(); ++j) { 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t candidate_index = candidate_bitmap_indices[j]; 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.push_back( 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_id_sizes[candidate_index].bitmap_id); 21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Construct FaviconRawBitmapResults from |best_favicon_id| and 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |best_bitmap_ids|. 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL icon_url; 21550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type; 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url, 2157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &icon_type)) { 21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < best_bitmap_ids.size(); ++i) { 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_updated; 2163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) favicon_base::FaviconRawBitmapResult bitmap_result; 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_url = icon_url; 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_type = icon_type; 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(best_bitmap_ids[i], 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &last_updated, 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.bitmap_data, 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.pixel_size)) { 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap_result.is_valid()) 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->push_back(bitmap_result); 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPageAndRedirects( 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 21830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 21840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& icon_ids) { 2185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find all the pages whose favicons we should set, we want to set it for 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all the pages in the redirect chain if it redirected. 21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirects; 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirects); 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save page <-> favicon associations. 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (history::RedirectList::const_iterator i(redirects.begin()); 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != redirects.end(); ++i) { 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed |= SetFaviconMappingsForPage(*i, icon_type, icon_ids); 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPage( 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 22050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_base::IconType icon_type, 22060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::vector<favicon_base::FaviconID>& icon_ids) { 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(icon_ids.size(), kMaxFaviconsPerPage); 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Two icon types are considered 'equivalent' if one of the icon types is 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TOUCH_ICON and the other is TOUCH_PRECOMPOSED_ICON. 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the icon mappings from |page_url| for |icon_type| to the favicons 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with |icon_ids|. Mappings for |page_url| to favicons of type |icon_type| 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whose FaviconID is not in |icon_ids| are removed. All icon mappings for 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |page_url| to favicons of a type equivalent to |icon_type| are removed. 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any favicons which are orphaned as a result of the removal of the 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon mappings. 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID> unmapped_icon_ids = icon_ids; 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings); 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 22270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch std::vector<favicon_base::FaviconID>::iterator icon_id_it = std::find( 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.begin(), unmapped_icon_ids.end(), m->icon_id); 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the icon mapping already exists, avoid removing it and adding it back. 22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_id_it != unmapped_icon_ids.end()) { 22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.erase(icon_id_it); 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if ((icon_type == favicon_base::TOUCH_ICON && 22370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch m->icon_type == favicon_base::TOUCH_PRECOMPOSED_ICON) || 22380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (icon_type == favicon_base::TOUCH_PRECOMPOSED_ICON && 22390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch m->icon_type == favicon_base::TOUCH_ICON) || 22400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (icon_type == m->icon_type)) { 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteIconMapping(m->mapping_id); 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removing the icon mapping may have orphaned the associated favicon so 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we must recheck it. This is not super fast, but this case will get 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered rarely, since normally a page will always map to the same 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon IDs. It will mostly happen for favicons we import. 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->HasMappingFor(m->icon_id)) 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteFavicon(m->icon_id); 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < unmapped_icon_ids.size(); ++i) { 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(page_url, unmapped_icon_ids[i]); 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetCachedRecentRedirects( 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirect_list) { 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(page_url); 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *redirect_list = iter->second; 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The redirect chain should have the destination URL as the last item. 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirect_list->empty()); 22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirect_list->back() == page_url); 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No known redirects, construct mock redirect chain containing |page_url|. 22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_list->push_back(page_url); 22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SendFaviconChangedNotificationForPageAndRedirects( 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url) { 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirect_list; 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirect_list); 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<FaviconChangedDetails> changed_details(new FaviconChangedDetails); 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirect_list.size(); ++i) 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.insert(redirect_list[i]); 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) changed_details.PassAs<HistoryDetails>()); 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Commit() { 2290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that a commit may not actually have been scheduled if a caller 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // explicitly calls this instead of using ScheduleCommit. Likewise, we 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may reset the flag written by a pending commit. But this is OK! It 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will merely cause extra commits (which is kind of the idea). We 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could optimize more for this case (we may get two extra commits in 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some cases) but it hasn't been important yet. 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 0) << 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Somebody left a transaction open"; 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleCommit() { 2314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = new CommitLaterTask(this); 231790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()), 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CancelScheduledCommit() { 2324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) { 23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_->Cancel(); 23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = NULL; 23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTaskImpl() { 2331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // db went away, release all the refs. 2333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_history_db_tasks_.clear(); 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any canceled tasks. 2338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch while (!queued_history_db_tasks_.empty()) { 2339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueuedHistoryDBTask& task = queued_history_db_tasks_.front(); 2340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!task.is_canceled()) { 2341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 2342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_history_db_tasks_.pop_front(); 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (queued_history_db_tasks_.empty()) 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the first task. 2349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueuedHistoryDBTask task = queued_history_db_tasks_.front(); 2350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_history_db_tasks_.pop_front(); 2351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (task.RunOnDBThread(this, db_.get())) { 2352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The task is done, notify the callback. 2353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task.DoneRunOnMainThread(); 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The task wants to run some more. Schedule it at the end of the current 2356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // tasks, and process it after an invoke later. 2357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_history_db_tasks_.insert(queued_history_db_tasks_.end(), task); 235890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTaskImpl, this)); 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generic operations 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURLs(urls); 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURL(const GURL& url) { 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(url); 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ExpireHistoryBetween( 23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<GURL>& restrict_urls, 23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time begin_time, 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_time) { 239158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!db_) 239258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 239458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (begin_time.is_null() && (end_time.is_null() || end_time.is_max()) && 239558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) restrict_urls.empty()) { 239658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Special case deleting all history so it can be faster and to reduce the 239758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // possibility of an information leak. 239858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DeleteAllHistory(); 239958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 240058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Clearing parts of history, have the expirer do the depend 240158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expirer_.ExpireHistoryBetween(restrict_urls, begin_time, end_time); 240258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 240358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, 240458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // we want to get it on disk ASAP. 240558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Commit(); 24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (begin_time <= first_recorded_time_) 24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 24102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 24112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistoryForTimes( 24132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::set<base::Time>& times, 24142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time begin_time, base::Time end_time) { 2415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (times.empty() || !db_) 24162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 24172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.begin() >= begin_time) 24192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Min time is before begin time: " 24202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime(); 24212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.rbegin() < end_time) 24222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Max time is after end time: " 24232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime(); 24242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history::QueryOptions options; 24262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.begin_time = begin_time; 24272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.end_time = end_time; 24282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES; 24292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryResults results; 243046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) QueryHistoryBasic(options, &results); 24312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1st pass: find URLs that are visited at one of |times|. 24332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<GURL> urls; 24342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 24352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times.count(results[i].visit_time()) > 0) 24362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) urls.insert(results[i].url()); 24372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 24382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.empty()) 24392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 24402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2nd pass: collect all visit times of those URLs. 24422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::Time> times_to_expire; 24432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 24442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.count(results[i].url())) 24452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.push_back(results[i].visit_time()); 24462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 24472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put the times in reverse chronological order and remove 24492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // duplicates (for expirer_.ExpireHistoryForTimes()). 24502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::sort(times_to_expire.begin(), times_to_expire.end(), 24512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::greater<base::Time>()); 24522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.erase( 24532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::unique(times_to_expire.begin(), times_to_expire.end()), 24542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.end()); 24552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Expires by times and commit. 24572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!times_to_expire.empty()); 24582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryForTimes(times_to_expire); 24592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 24602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(times_to_expire.back() >= first_recorded_time_); 24622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if we expired it. 24632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times_to_expire.back() == first_recorded_time_) 24642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 24652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistory( 24682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<history::ExpireHistoryArgs>& expire_list) { 2469b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 24702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool update_first_recorded_time = false; 24712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<history::ExpireHistoryArgs>::const_iterator it = 24732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.begin(); it != expire_list.end(); ++it) { 24742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryBetween(it->urls, it->begin_time, it->end_time); 24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->begin_time < first_recorded_time_) 24772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) update_first_recorded_time = true; 24782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 24792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 24802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if any deletion might have affected it. 24822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (update_first_recorded_time) 24832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 24842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) { 2488b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { 24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*i, &url_row)) 24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // The URL isn't in the db; nothing to do. 24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(url_row.id(), &visits); 24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.empty()) 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(*i); // There are no more visits; nuke the URL. 25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void HistoryBackend::DatabaseErrorCallback(int error, sql::Statement* stmt) { 25057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!scheduled_kill_db_ && sql::IsErrorCatastrophic(error)) { 25067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = true; 25077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Don't just do the close/delete here, as we are being called by |db| and 25087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // that seems dangerous. 25097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // TODO(shess): Consider changing KillHistoryDatabase() to use 25107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // RazeAndClose(). Then it can be cleared immediately. 25117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::MessageLoop::current()->PostTask( 25127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) FROM_HERE, 25137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::KillHistoryDatabase, this)); 25147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 25157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 25167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::KillHistoryDatabase() { 25187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = false; 2519b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rollback transaction because Raze() cannot be called from within a 25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction. 25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RollbackTransaction(); 25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = db_->Raze(); 25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success); 25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The expirer keeps tabs on the active databases. Tell it about the 25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // databases which will be closed. 253546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) expirer_.SetDatabases(NULL, NULL); 25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). 25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTask( 2543116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<HistoryDBTask> task, 2544116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<base::SingleThreadTaskRunner> origin_loop, 2545116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::CancelableTaskTracker::IsCanceledCallback& is_canceled) { 2546116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool scheduled = !queued_history_db_tasks_.empty(); 2547116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_history_db_tasks_.insert( 2548116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch queued_history_db_tasks_.end(), 2549116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueuedHistoryDBTask(task, origin_loop, is_canceled)); 2550116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!scheduled) 25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDBTaskImpl(); 25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::BroadcastNotifications( 25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 2556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<HistoryDetails> details) { 25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |delegate_| may be NULL if |this| is in the process of closing (closed by 2558b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // HistoryService -> HistoryBackend::Closing(). 2559b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 2560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delegate_->BroadcastNotifications(type, details.Pass()); 25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid HistoryBackend::NotifySyncURLsModified(URLRows* rows) { 25640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (typed_url_syncable_service_.get()) 25650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch typed_url_syncable_service_->OnUrlsModified(rows); 25660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 25670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2568b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void HistoryBackend::NotifySyncURLsDeleted(bool all_history, 256946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool expired, 2570b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRows* rows) { 2571b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 257246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) typed_url_syncable_service_->OnUrlsDeleted(all_history, expired, rows); 2573b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 2574b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Deleting -------------------------------------------------------------------- 25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllHistory() { 25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our approach to deleting all history is: 25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Copy the bookmarks and their dependencies to new tables with temporary 25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // names. 25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. Delete the original tables. Since tables can not share pages, we know 25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that any data we don't want to keep is now in an unused page. 25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3. Renaming the temporary tables to match the original. 25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4. Vacuuming the database to delete the unused pages. 25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we are likely to have very few bookmarks and their dependencies 25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compared to all history, this is also much faster than just deleting from 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original tables directly. 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the bookmarked URLs. 259146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<URLAndTitle> starred_urls; 259246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) HistoryClient* history_client = GetHistoryClient(); 259346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (history_client) 259446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) history_client->GetBookmarks(&starred_urls); 25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRows kept_urls; 25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < starred_urls.size(); i++) { 25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(starred_urls[i].url, &row)) 26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the last visit time so when we write these rows they are "clean." 26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_last_visit(Time()); 26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_visit_count(0); 26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_typed_count(0); 26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.push_back(row); 26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear thumbnail and favicon history. The favicons for the given URLs will 26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be kept. 26113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!ClearAllThumbnailHistory(kept_urls)) { 26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Thumbnail history could not be cleared"; 26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We continue in this error case. If the user wants to delete their 26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history, we should delete as much as we can. 26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 261758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // ClearAllMainHistory will change the IDs of the URLs in kept_urls. 261858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Therefore, we clear the list afterwards to make sure nobody uses this 261958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // invalid data. 26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ClearAllMainHistory(kept_urls)) 26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Main history could not be cleared"; 26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.clear(); 26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Send out the notification that history is cleared. The in-memory database 26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will pick this up and clear itself. 2628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails); 26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->all_history = true; 2630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NotifySyncURLsDeleted(true, false, NULL); 2631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, 2632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) details.PassAs<HistoryDetails>()); 26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool HistoryBackend::ClearAllThumbnailHistory(const URLRows& kept_urls) { 2636b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we have no reference to the thumbnail database, maybe there was an 26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error opening it. In this case, we just try to blow it away to try to 26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fix the error if it exists. This may fail, in which case either the 26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file doesn't exist or there's no more we can do. 26413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sql::Connection::Delete(GetFaviconsFileName()); 26423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 26433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Older version of the database. 2644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetThumbnailFileName()); 26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Urls to retain mappings for. 26493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<GURL> urls_to_keep; 26503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); 26513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) i != kept_urls.end(); ++i) { 26523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) urls_to_keep.push_back(i->url()); 26533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Isolate from any long-running transaction. 26563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 26573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(shess): If this fails, perhaps the database should be razed 26603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // or deleted. 26613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!thumbnail_db_->RetainDataForPageUrls(urls_to_keep)) { 26623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->RollbackTransaction(); 26633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 26643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO (michaelbai): Add the unit test once AndroidProviderBackend is 26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avaliable in HistoryBackend. 26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->ClearAndroidURLRows(); 26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to remove all the pages associated with the dropped tables. There 26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must be no transaction open on the table when we do this. We assume that 26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our long-running transaction is open, so we complete it and start it again. 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 1); 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->Vacuum(); 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::ClearAllMainHistory(const URLRows& kept_urls) { 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the duplicate URL table. We will copy the kept URLs into this. 26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CreateTemporaryURLTable()) 26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 268858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Insert the URLs into the temporary table. 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); i != kept_urls.end(); 26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 269158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) db_->AddTemporaryURL(*i); 26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the original URL table with the temporary one. 26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CommitTemporaryURLTable()) 26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the old tables and recreate them empty. 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RecreateAllTablesButURL(); 27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to reclaim the space from the dropped tables. This must be done 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when there is no transaction open, and we assume that our long-running 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction is currently open. 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Vacuum(); 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 271246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)HistoryClient* HistoryBackend::GetHistoryClient() { 271346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (history_client_) 271446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) history_client_->BlockUntilBookmarksLoaded(); 271546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return history_client_; 27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { 27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BriefVisitInfo info; 27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.url_id = visit.url_id; 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.time = visit.visit_time; 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.transition = visit.transition; 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have a delegate yet during setup or shutdown, we will drop 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these notifications. 2725b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->NotifyVisitDBObserversOnAddVisit(info); 27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 2730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::PopulateMostVisitedURLMap() { 2731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MostVisitedURLList most_visited_urls; 2732116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueryMostVisitedURLs( 2733116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch kPageVisitStatsMaxTopSites, kSegmentDataRetention, &most_visited_urls); 2734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_LE(most_visited_urls.size(), kPageVisitStatsMaxTopSites); 2736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < most_visited_urls.size(); ++i) { 2737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].url] = i; 2738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < most_visited_urls[i].redirects.size(); ++j) 2739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].redirects[j]] = i; 2740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::RecordTopPageVisitStats(const GURL& url) { 2744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int rank = kPageVisitStatsMaxTopSites; 2745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); 2746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it != most_visited_urls_map_.end()) 2747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank = (*it).second; 2748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", 2749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank, kPageVisitStatsMaxTopSites + 1); 2750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 2752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 2754