history_backend.cc revision 58537e28ecd584eab876aee8be7156509866d23a
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_backend.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <functional> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 17bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/files/file_enumerator.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h" 209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/rand_util.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/history_url_provider.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_service.h" 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/favicon/favicon_changed_details.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/download_row.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_db_task.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_notifications.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_publisher.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/in_memory_history_backend.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/page_usage_data.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/select_favicon_frames.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/top_sites.h" 38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/browser/history/typed_url_syncable_service.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/visit_filter.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/importer/imported_favicon_usage.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/error_delegate_util.h" 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/android/android_provider_backend.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The HistoryBackend consists of a number of components: 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase (stores past 3 months of history) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase (stores a list of URLs) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadDatabase (stores a list of downloads) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase (stores a list of visits for the URLs) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSegmentDatabase (stores groups of URLs for the most visited view). 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ArchivedDatabase (stores history older than 3 months) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase (stores a list of URLs) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadDatabase (stores a list of downloads) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase (stores a list of visits for the URLs) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (this does not store visit segments as they expire after 3 mos.) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpireHistoryBackend (manages moving things from HistoryDatabase to 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) the ArchivedDatabase and deleting) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we keep segment data for in days. Currently 3 months. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This value needs to be greater or equal to 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dependency between MostVisitedModel and the history backend. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSegmentDataRetention = 90; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How long we'll wait to do a commit, so that things are batched together. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCommitIntervalSeconds = 10; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of time before we re-fetch the favicon. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kFaviconRefetchDays = 7; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetSessionTabs returns all open tabs, or tabs closed kSessionCloseTimeWindow 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// seconds ago. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSessionCloseTimeWindowSecs = 10; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum number of items we'll allow in the redirect list before 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deleting some. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxRedirectCount = 32; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The number of days old a history entry can be before it is considered "old" 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and is archived. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kArchiveDaysThreshold = 90; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The maximum number of top sites to track when recording top page visit stats. 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic const size_t kPageVisitStatsMaxTopSites = 50; 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts from PageUsageData to MostVisitedURL. |redirects| is a 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// list of redirects for this URL. Empty list means no redirects. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RedirectList& redirects) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL mv; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.url = page_data.GetURL(); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.title = page_data.GetTitle(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirects.empty()) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirects must contain at least the target url. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects = redirects; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mv.redirects[mv.redirects.size() - 1] != mv.url) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last url must be the target url. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mv.redirects.push_back(mv.url); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mv; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This task is run on a timer so that commits happen at regular intervals 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so they are batched together. The important thing about this class is that 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it supports canceling of the task so the reference to the backend will be 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// freed. The problem is that when history is shutting down, there is likely 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be one of these commits still pending and holding a reference. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The backend can call Cancel to have this task release the reference. The 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// task will still run (if we ever get to processing the event before 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shutdown), but it will not do anything. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that this is a refcounted object and is not a task in itself. It should 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be assigned to a RunnableMethod. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(brettw): bug 1165182: This should be replaced with a 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::WeakPtrFactory which will handle everything automatically (like we do 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in ExpireHistoryBackend). 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CommitLaterTask : public base::RefCounted<CommitLaterTask> { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CommitLaterTask(HistoryBackend* history_backend) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : history_backend_(history_backend) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The backend will call this function if it is being destroyed so that we 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release our reference. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Cancel() { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_ = NULL; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunCommit() { 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (history_backend_.get()) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_backend_->Commit(); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCounted<CommitLaterTask>; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~CommitLaterTask() {} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryBackend> history_backend_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HistoryBackend -------------------------------------------------------------- 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HistoryBackend::HistoryBackend(const base::FilePath& history_dir, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(delegate), 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id_(id), 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_dir_(history_dir), 1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_(false), 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expirer_(this, bookmark_service), 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recent_redirects_(kMaxRedirectCount), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_(NULL), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_(false), 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_(bookmark_service) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HistoryBackend::~HistoryBackend() { 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!scheduled_commit_.get()) << "Deleting without cleanup"; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseDBTasks(); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First close the databases before optionally running the "destroy" task. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!backend_destroy_task_.is_null()) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify an interested party (typically a unit test) that we're done. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(backend_destroy_message_loop_); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_->PostTask(FROM_HERE, backend_destroy_task_); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetAndroidCacheFileName()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Init(const std::string& languages, bool force_fail) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!force_fail) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitImpl(languages); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->DBLoaded(id_); 212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_.reset(new TypedUrlSyncableService(this)); 213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch memory_pressure_listener_.reset(new base::MemoryPressureListener( 214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&HistoryBackend::OnMemoryPressure, base::Unretained(this)))); 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PopulateMostVisitedURLMap(); 217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryBackend::SetOnBackendDestroyTask(base::MessageLoop* message_loop, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& task) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!backend_destroy_task_.is_null()) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Setting more than one destroy task, overriding"; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_message_loop_ = message_loop; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_destroy_task_ = task; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Closing() { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Any scheduled commit will have a reference to us, we must make it 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release that reference before we can be destroyed. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release our reference to the delegate, this reference will be keeping the 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history service alive. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_.reset(); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::NotifyRenderProcessHostDestruction(const void* host) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker_.NotifyRenderProcessHostDestruction(host); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetThumbnailFileName() const { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kThumbnailsFilename); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetFaviconsFileName() const { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kFaviconsFilename); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetArchivedFileName() const { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kArchivedHistoryFilename); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath HistoryBackend::GetAndroidCacheFileName() const { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return history_dir_.Append(chrome::kAndroidCacheFilename); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SegmentID HistoryBackend::GetLastSegmentID(VisitID from_visit) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set is used to detect referrer loops. Should not happen, but can 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the database is corrupt. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = from_visit; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (visit_id) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow row; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForVisit(visit_id, &row)) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row.segment_id) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row.segment_id; // Found a visit in this change with a segment. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the referrer of this visit, if any. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_id = row.referring_visit; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(visit_id) != visit_set.end()) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in referer chain, giving up"; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(visit_id); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SegmentID HistoryBackend::UpdateSegments( 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID from_visit, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition_type, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Time ts) { 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only consider main frames. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!content::PageTransitionIsMainFrame(transition_type)) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SegmentID segment_id = 0; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(transition_type); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Are we at the beginning of a new segment? 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that navigating to an existing entry (with back/forward) reuses the 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same transition type. We are not adding it as a new segment in that case 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because if this was the target of a redirect, we might end up with 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2 entries for the same final URL. Ex: User types google.net, gets 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirected to google.com. A segment is created for google.net. On 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // google.com users navigates through a link, then press back. That last 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation is for the entry google.com transition typed. We end up adding 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a segment for that one as well. So we end up with google.net and google.com 31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // in the segment table, showing as 2 entries in the NTP. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note also that we should still be updating the visit count for that segment 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which we are not doing now. It should be addressed when 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://crbug.com/96860 is fixed. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((t == content::PAGE_TRANSITION_TYPED || 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t == content::PAGE_TRANSITION_AUTO_BOOKMARK) && 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (transition_type & content::PAGE_TRANSITION_FORWARD_BACK) == 0) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If so, create or get the segment. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string segment_name = db_->ComputeSegmentName(url); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(segment_id = db_->GetSegmentNamed(segment_name))) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(segment_id = db_->CreateSegment(url_id, segment_name))) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: if we update an existing segment, we update the url used to 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // represent that segment in order to minimize stale most visited 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // images. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateSegmentRepresentationURL(segment_id, url_id); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: it is possible there is no segment ID set for this visit chain. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This can happen if the initial navigation wasn't AUTO_BOOKMARK or 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TYPED. (For example GENERATED). In this case this visit doesn't count 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // toward any segment. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(segment_id = GetLastSegmentID(from_visit))) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the segment in the visit. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->SetSegmentID(visit_id, segment_id)) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally, increase the counter for that segment / day. 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->IncreaseSegmentVisitCount(segment_id, ts, 1)) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return segment_id; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateWithPageEndTime(const void* host, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 page_id, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_ts) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be filled with the URL ID and the visit ID of the last addition. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = tracker_.GetLastVisit(host, page_id, url); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(visit_id, end_ts); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateVisitDuration(VisitID visit_id, const Time end_ts) { 367b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the starting visit_time for visit_id. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_row; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetRowForVisit(visit_id, &visit_row)) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should never have a negative duration time even when time is skewed. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.visit_duration = end_ts > visit_row.visit_time ? 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_ts - visit_row.visit_time : TimeDelta::FromMicroseconds(0); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateVisitRow(visit_row); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPage(const HistoryAddPageArgs& request) { 381b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be filled with the URL ID and the visit ID of the last addition. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<URLID, VisitID> last_ids(0, tracker_.GetLastVisit( 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.id_scope, request.page_id, request.referrer)); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID from_visit_id = last_ids.second; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a redirect chain is given, we expect the last item in that chain to be 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the final URL. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request.redirects.empty() || 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects.back() == request.url); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is adding older history, we need to make sure our times 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are correct. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.time < first_recorded_time_) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = request.time; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition request_transition = request.transition; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition stripped_transition = 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(request_transition); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_keyword_generated = 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition == content::PAGE_TRANSITION_KEYWORD_GENERATED); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user is navigating to a not-previously-typed intranet hostname, 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change the transition to TYPED so that the omnibox will learn that this is 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a known host. 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_redirects = request.redirects.size() > 1; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionIsMainFrame(request_transition) && 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stripped_transition != content::PAGE_TRANSITION_TYPED) && 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_keyword_generated) { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& origin_url(has_redirects ? 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.redirects[0] : request.url); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (origin_url.SchemeIs(chrome::kHttpScheme) || 416424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) origin_url.SchemeIs(content::kHttpsScheme) || 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origin_url.SchemeIs(chrome::kFtpScheme)) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host(origin_url.host()); 419a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) size_t registry_length = 420a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::GetRegistryLength( 421a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) host, 422a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, 423a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); 424a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (registry_length == 0 && !db_->IsTypedHost(host)) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition = content::PAGE_TRANSITION_TYPED; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition = 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition | 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionGetQualifier(request_transition)); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_redirects) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The single entry is both a chain start and end. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = content::PageTransitionFromInt( 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_transition | 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect case (one element means just the page itself). 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids = AddPageVisit(request.url, request.time, 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids.second, t, request.visit_source); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the segment for this visit. KEYWORD_GENERATED visits should not 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // result in changing most visited, so we don't update segments (most 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visited db). 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_keyword_generated) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateSegments(request.url, from_visit_id, last_ids.second, t, 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.time); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the referrer's duration. 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(from_visit_id, request.time); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Redirect case. Add the redirect chain. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition redirect_info = 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects = request.redirects; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirects[0].SchemeIs(chrome::kAboutScheme)) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the redirect source + referrer is "about" we skip it. This 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happens when a page opens a new frame/window to about:blank and then 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // script sets the URL to somewhere else (used to hide the referrer). It 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // would be nice to keep all these redirects properly but we don't ever 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // see the initial about:blank load, so we don't know where the 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subsequent client redirect came from. 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this case, we just don't bother hooking up the source of the 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirects, so we remove it. 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects.erase(redirects.begin()); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (request_transition & content::PAGE_TRANSITION_CLIENT_REDIRECT) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_info = content::PAGE_TRANSITION_CLIENT_REDIRECT; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The first entry in the redirect chain initiated a client redirect. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't add this to the database since the referrer is already 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there, so we skip over it but change the transition type of the first 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transition to client redirect. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The referrer is invalid when restoring a session that features an 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // https tab that redirects to a different host or to http. In this 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case we don't need to reconnect the new redirect with the existing 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chain. 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.referrer.is_valid()) { 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(request.referrer == redirects[0]); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects.erase(redirects.begin()); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the navigation entry for this visit has replaced that for the 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first visit, remove the CHAIN_END marker from the first visit. This 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can be called a lot, for example, the page cycler, and most of the 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time we won't have changed anything. 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_row; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request.did_replace_entry && 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetRowForVisit(last_ids.second, &visit_row) && 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition & content::PAGE_TRANSITION_CHAIN_END) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition = content::PageTransitionFromInt( 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_row.transition & ~content::PAGE_TRANSITION_CHAIN_END); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateVisitRow(visit_row); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t redirect_index = 0; redirect_index < redirects.size(); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_index++) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition t = 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt(stripped_transition | redirect_info); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is the last transition, add a CHAIN_END marker 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (redirect_index == (redirects.size() - 1)) { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t = content::PageTransitionFromInt( 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t | content::PAGE_TRANSITION_CHAIN_END); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record all redirect visits with the same timestamp. We don't display 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them anyway, and if we ever decide to, we can reconstruct their order 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the redirect chain. 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids = AddPageVisit(redirects[redirect_index], 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.time, last_ids.second, 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t, request.visit_source); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (t & content::PAGE_TRANSITION_CHAIN_START) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the segment for this visit. 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateSegments(redirects[redirect_index], 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) from_visit_id, last_ids.second, t, request.time); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the visit_details for this visit. 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisitDuration(from_visit_id, request.time); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Subsequent transitions in the redirect list must all be server 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // redirects. 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_info = content::PAGE_TRANSITION_SERVER_REDIRECT; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Last, save this redirect chain for later so we can set titles & favicons 535bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // on the redirected pages properly. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recent_redirects_.Put(request.url, redirects); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the last visit to the tracker so we can get outgoing transitions. 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(evanm): Due to http://b/1194536 we lose the referrers of a subframe 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation anyway, so last_visit_id is always zero for them. But adding 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them here confuses main frame history, so we skip them for now. 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stripped_transition != content::PAGE_TRANSITION_AUTO_SUBFRAME && 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped_transition != content::PAGE_TRANSITION_MANUAL_SUBFRAME && 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !is_keyword_generated) { 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracker_.AddVisit(request.id_scope, request.page_id, request.url, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_ids.second); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::InitImpl(const std::string& languages) { 557b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(!db_) << "Initializing HistoryBackend twice"; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the rare case where the db fails to initialize a dialog may get shown 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the blocks the caller, yet allows other messages through. For this reason 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we only set db_ to the created database if creation is successful. That 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // way other methods won't do anything as db_ is still NULL. 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Compute the file names. 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath history_name = history_dir_.Append(chrome::kHistoryFilename); 5673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::FilePath thumbnail_name = GetFaviconsFileName(); 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath archived_name = GetArchivedFileName(); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 570bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Delete the old index database files which are no longer used. 571bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch DeleteFTSIndexDatabases(); 572bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // History database. 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(new HistoryDatabase()); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Unretained to avoid a ref loop with db_. 5777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) db_->set_error_callback( 5787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::DatabaseErrorCallback, 5797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Unretained(this))); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sql::InitStatus status = db_->Init(history_name); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case sql::INIT_OK: 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case sql::INIT_FAILURE: { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A NULL db_ will cause all calls on this object to notice this error 5877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // and to not continue. If the error callback scheduled killing the 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database, the task it posted has not executed yet. Try killing the 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database now before we close it. 5907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool kill_db = scheduled_kill_db_; 5917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (kill_db) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KillHistoryDatabase(); 5937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.AttemptedToFixProfileError", kill_db); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->NotifyProfileError(id_, status); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill the in-memory database and send it back to the history service on the 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main thread. 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InMemoryHistoryBackend* mem_backend = new InMemoryHistoryBackend; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mem_backend->Init(history_name, db_.get())) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->SetInMemoryBackend(id_, mem_backend); // Takes ownership of 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pointer. 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete mem_backend; // Error case, run without the in-memory DB. 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginExclusiveMode(); // Must be after the mem backend read the data. 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 612bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Create the history publisher which needs to be passed on to the thumbnail 613bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // database for publishing history. 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_publisher_.reset(new HistoryPublisher()); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!history_publisher_->Init()) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The init may fail when there are no indexers wanting our history. 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hence no need to log the failure. 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_publisher_.reset(); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Thumbnail database. 6223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(shess): "thumbnail database" these days only stores 6233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // favicons. Thumbnails are stored in "top sites". Consider 6243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // renaming "thumbnail" references to "favicons" or something of the 6253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // sort. 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(new ThumbnailDatabase()); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thumbnail_db_->Init(thumbnail_name, 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_publisher_.get(), 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.get()) != sql::INIT_OK) { 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unlike the main database, we don't error out when the database is too 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new because this error is much less severe. Generally, this shouldn't 63258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // happen since the thumbnail and main database versions should be in sync. 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'll just continue without thumbnails & favicons in this case or any 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other error. 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the thumbnail database."; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Archived database. 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->needs_version_17_migration()) { 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See needs_version_17_migration() decl for more. In this case, we want 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to delete the archived database and need to do so before we try to 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // open the file. We can ignore any error (maybe the file doesn't exist). 644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(archived_name); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(new ArchivedDatabase()); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!archived_db_->Init(archived_name)) { 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the archived database."; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Generate the history and thumbnail database metrics only after performing 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any migration work. 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::RandInt(1, 100) == 50) { 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Only do this computation sometimes since it can be expensive. 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->ComputeDatabaseMetrics(history_name); 6572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (thumbnail_db_) 6582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch thumbnail_db_->ComputeDatabaseMetrics(); 6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tell the expiration module about all the nice databases we made. This must 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happen before db_->Init() is called since the callback ForceArchiveHistory 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may need to expire stuff. 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // *sigh*, this can all be cleaned up when that migration code is removed. 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The main DB initialization should intuitively be first (not that it 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually matters) and the expirer should be set last. 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.SetDatabases(db_.get(), archived_db_.get(), 669bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch thumbnail_db_.get()); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open the long-running transaction. 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 673b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 675b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the first item in our database. 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start expiring old stuff. 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.StartArchivingOldStuff(TimeDelta::FromDays(kArchiveDaysThreshold)); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 685b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(new AndroidProviderBackend( 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAndroidCacheFileName(), db_.get(), thumbnail_db_.get(), 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_, delegate_.get())); 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HISTOGRAM_TIMES("History.InitTime", 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 696ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid HistoryBackend::OnMemoryPressure( 697ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool trim_aggressively = memory_pressure_level == 699ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL; 700ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (db_) 701ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db_->TrimMemory(trim_aggressively); 702ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (thumbnail_db_) 703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch thumbnail_db_->TrimMemory(trim_aggressively); 704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (archived_db_) 705ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch archived_db_->TrimMemory(trim_aggressively); 706ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 707ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloseAllDatabases() { 709b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Commit the long-running transaction. 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.reset(); 71358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Forget the first recorded time since the database is closed. 71458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) first_recorded_time_ = base::Time(); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 716b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_.reset(); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 720b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->CommitTransaction(); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::pair<URLID, VisitID> HistoryBackend::AddPageVisit( 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time time, 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID referring_visit, 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition, 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Top-level frame navigations are visible, everything else is hidden 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool new_hidden = !content::PageTransitionIsMainFrame(transition); 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: This code must stay in sync with 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExpireHistoryBackend::ExpireURLsForVisits(). 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkasting): http://b/1148304 We shouldn't be marking so many URLs as 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typed, which would eliminate the need for this code. 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int typed_increment = 0; 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition_type = 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionStripQualifier(transition); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((transition_type == content::PAGE_TRANSITION_TYPED && 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !content::PageTransitionIsRedirect(transition)) || 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition_type == content::PAGE_TRANSITION_KEYWORD_GENERATED) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typed_increment = 1; 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Only count the page visit if it came from user browsing and only count it 749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // once when cycling through a redirect chain. 750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (visit_source == SOURCE_BROWSED && 751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (transition & content::PAGE_TRANSITION_CHAIN_END) != 0) { 752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RecordTopPageVisitStats(url); 753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if this URL is already in the DB. 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update of an existing row. 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::PageTransitionStripQualifier(transition) != 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_RELOAD) 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(url_info.visit_count() + 1); 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typed_increment) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(url_info.typed_count() + typed_increment); 766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (url_info.last_visit() < time) 767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_info.set_last_visit(time); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only allow un-hiding of pages, never hiding. 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_hidden) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(url_id, url_info); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Addition of a new row. 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(1); 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(typed_increment); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(time); 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(new_hidden); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_id = db_->AddURL(url_info); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding URL failed."; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(0, 0); 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.id_ = url_id; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the visit with the time to the database. 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, time, referring_visit, transition, 0); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID visit_id = db_->AddVisit(&visit_info, visit_source); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification of the visit. 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_id) { 799b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 800b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlVisited(transition, &url_info); 801b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLVisitedDetails* details = new URLVisitedDetails; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->transition = transition; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->row = url_info; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(meelapshah) Disabled due to potential PageCycler regression. 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-enable this. 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetMostRecentRedirectsTo(url, &details->redirects); 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URL_VISITED, details); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to build visit insert statement: " 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "url_id = " << url_id; 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::make_pair(url_id, visit_id); 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPagesWithDetails(const URLRows& urls, 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 819b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> modified(new URLsModifiedDetails); 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = urls.begin(); i != urls.end(); ++i) { 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!i->last_visit().is_null()); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will add to either the archived database or the main one depending on 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the date of the added visit. 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLDatabase* url_database; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase* visit_database; 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsExpiredVisitTime(i->last_visit())) { 831b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!archived_db_) 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // No archived database to save it to, just forget this. 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_database = archived_db_.get(); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_database = archived_db_.get(); 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_database = db_.get(); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_database = db_.get(); 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow existing_url; 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = url_database->GetRowForURL(i->url(), &existing_url); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the page if it doesn't exist. 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_id = url_database->AddURL(*i); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_id) { 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Could not add row to DB"; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->typed_count() > 0) { 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modified->changed_urls.push_back(*i); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modified->changed_urls.back().set_id(url_id); // *i likely has |id_| 0. 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sync code manages the visits itself. 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_source != SOURCE_SYNCED) { 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make up a visit to correspond to the last visit to the page. 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit_info(url_id, i->last_visit(), 0, 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransitionFromInt( 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_LINK | 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_START | 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_CHAIN_END), 0); 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!visit_database->AddVisit(&visit_info, visit_source)) { 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Adding visit failed."; 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyVisitObservers(visit_info); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_info.visit_time < first_recorded_time_) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_recorded_time_ = visit_info.visit_time; 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 876b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&modified->changed_urls); 877b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast a notification for typed URLs that have been modified. This 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be picked up by the in-memory URL database on the main thread. 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1140015: Add an "add page" notification so the history 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views can keep in sync. 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modified.release()); 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) { 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return time < expirer_.GetCurrentArchiveTime(); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetPageTitle(const GURL& url, 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title) { 895b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search for recent redirects which should get the same title. We make a 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dummy list containing the exact URL visited if there are no redirects so 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the processing below can be the same. 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList dummy_list; 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects; 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(url); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &iter->second; 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This redirect chain should have the destination URL as the last item. 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirects->empty()); 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirects->back() == url); 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No redirect chain stored, make up one containing the URL we want so we 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can use the same logic below. 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dummy_list.push_back(url); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects = &dummy_list; 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLsModifiedDetails> details(new URLsModifiedDetails); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirects->size(); i++) { 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID row_id = db_->GetRowForURL(redirects->at(i), &row); 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row_id && row.title() != title) { 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_title(title); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->UpdateURLRow(row_id, row); 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->changed_urls.push_back(row); 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Broadcast notifications for any URLs that have changed. This will 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the in-memory database and the InMemoryURLIndex. 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!details->changed_urls.empty()) { 931b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 932b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsModified(&details->changed_urls); 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details.release()); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::AddPageNoVisitForBookmark(const GURL& url, 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title) { 941b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(url); 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID url_id = db_->GetRowForURL(url, &url_info); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_id) { 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is already known, nothing to do. 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!title.empty()) { 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_title(title); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_title(UTF8ToUTF16(url.spec())); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(Time::Now()); 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the page hidden. If the user types it in, it'll unhide. 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(true); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::IterateURLs( 96590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const scoped_refptr<visitedlink::VisitedLinkDelegate::URLEnumerator>& 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator) { 967b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDatabase::URLEnumerator e; 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->InitURLEnumeratorForEverything(&e)) { 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (e.GetNextURL(&info)) { 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iterator->OnURL(info.url()); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(true); // Success. 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterator->OnComplete(false); // Failure. 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetAllTypedURLs(URLRows* urls) { 982b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetAllTypedUrls(urls); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsForURL(URLID id, VisitVector* visits) { 988b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetVisitsForURL(id, visits); 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentVisitsForURL(URLID id, 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits, 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 996b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetMostRecentVisitsForURL(id, max_visits, visits); 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::UpdateURL(URLID id, const history::URLRow& url) { 1002b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->UpdateURLRow(id, url); 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::AddVisits(const GURL& url, 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<VisitInfo>& visits, 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSource visit_source) { 1010b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<VisitInfo>::const_iterator visit = visits.begin(); 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit != visits.end(); ++visit) { 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddPageVisit( 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, visit->first, 0, visit->second, visit_source).first) { 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::RemoveVisits(const VisitVector& visits) { 1025b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.ExpireVisits(visits); 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetVisitsSource(const VisitVector& visits, 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSourceMap* sources) { 1035b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsSource(visits, sources); 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetURL(const GURL& url, history::URLRow* url_row) { 1043b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->GetRowForURL(url, url_row) != 0; 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryURL(scoped_refptr<QueryURLRequest> request, 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool want_visits) { 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow* row = &request->value.a; 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits = &request->value.b; 1057b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetRowForURL(url, row)) { 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have a row. 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = true; 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optionally query the visits. 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (want_visits) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(row->id(), visits); 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), success, row, visits); 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1070b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TypedUrlSyncableService* HistoryBackend::GetTypedUrlSyncableService() const { 1071b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return typed_url_syncable_service_.get(); 1072b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 1073b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Segment usage --------------------------------------------------------------- 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteOldSegmentData() { 1077b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteSegmentData(Time::Now() - 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kSegmentDataRetention)); 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QuerySegmentUsage( 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QuerySegmentUsageRequest> request, 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Time from_time, 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_result_count) { 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1089b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(from_time, max_result_count, &request->value.get()); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is the first time we query segments, invoke 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DeleteOldSegmentData asynchronously. We do this to cleanup old 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entries. 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!segment_queried_) { 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) segment_queried_ = true; 109790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&HistoryBackend::DeleteOldSegmentData, this)); 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value.get()); 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::IncreaseSegmentDuration(const GURL& url, 11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time time, 11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta delta) { 1108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string segment_name(VisitSegmentDatabase::ComputeSegmentName(url)); 11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SegmentID segment_id = db_->GetSegmentNamed(segment_name); 11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!segment_id) { 11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) URLID url_id = db_->GetRowForURL(url, NULL); 11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!url_id) 11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) segment_id = db_->CreateSegment(url_id, segment_name); 11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!segment_id) 11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SegmentDurationID duration_id; 11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta total_delta; 11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!db_->GetSegmentDuration(segment_id, time, &duration_id, 11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &total_delta)) { 11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->CreateSegmentDuration(segment_id, time, delta); 11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) total_delta += delta; 11292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->SetSegmentDuration(duration_id, total_delta); 11302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::QuerySegmentDuration( 11332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<QuerySegmentUsageRequest> request, 11342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Time from_time, 11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int max_result_count) { 11362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request->canceled()) 11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->QuerySegmentDuration(from_time, max_result_count, 11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &request->value.get()); 11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request->ForwardResult(request->handle(), &request->value.get()); 11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keyword visits -------------------------------------------------------------- 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetKeywordSearchTermsForURL(const GURL& url, 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& term) { 1151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the ID for this URL. 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(url, &url_row)) { 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a small possibility the url was deleted before the keyword 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was added. Ignore the request. 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->SetKeywordSearchTermsForURL(url_row.id(), keyword_id, term); 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // details is deleted by BroadcastNotifications. 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KeywordSearchTermDetails* details = new KeywordSearchTermDetails; 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->url = url; 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->keyword_id = keyword_id; 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->term = term; 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications( 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, details); 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllSearchTermsForKeyword( 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id) { 1176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->DeleteAllSearchTermsForKeyword(keyword_id); 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky): bug 1168470. Need to move from archive dbs too. 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetMostRecentKeywordSearchTerms( 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request, 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateURLID keyword_id, 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& prefix, 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_count) { 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetMostRecentKeywordSearchTerms(keyword_id, prefix, max_count, 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &(request->value)); 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Downloads ------------------------------------------------------------------- 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HistoryBackend::GetNextDownloadId(uint32* next_id) { 1202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 12037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db_->GetNextDownloadId(next_id); 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get all the download entries from the database. 12072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::QueryDownloads(std::vector<DownloadRow>* rows) { 1208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) 12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->QueryDownloads(rows); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Update a particular download entry. 12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::UpdateDownload(const history::DownloadRow& data) { 1214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->UpdateDownload(data); 12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::CreateDownload(const history::DownloadRow& history_info, 12217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool* success) { 1222b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 12232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 12247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *success = db_->CreateDownload(history_info); 12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleCommit(); 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HistoryBackend::RemoveDownloads(const std::set<uint32>& ids) { 1229b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 12317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_before = db_->CountDownloads(); 12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks started_removing = base::TimeTicks::Now(); 12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HistoryBackend uses a long-running Transaction that is committed 12342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // periodically, so this loop doesn't actually hit the disk too hard. 12357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (std::set<uint32>::const_iterator it = ids.begin(); 12367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch it != ids.end(); ++it) { 12372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->RemoveDownload(*it); 12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScheduleCommit(); 12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks finished_removing = base::TimeTicks::Now(); 12417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t downloads_count_after = db_->CountDownloads(); 12427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 12437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_LE(downloads_count_after, downloads_count_before); 12447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (downloads_count_after > downloads_count_before) 12457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 12467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t num_downloads_deleted = downloads_count_before - downloads_count_after; 12477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCount", 12487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch num_downloads_deleted); 12497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::TimeDelta micros = (1000 * (finished_removing - started_removing)); 12507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTime", micros); 12517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (num_downloads_deleted > 0) { 12527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_TIMES("Download.DatabaseRemoveDownloadsTimePerRecord", 12537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (1000 * micros) / num_downloads_deleted); 12542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_GE(ids.size(), num_downloads_deleted); 12567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (ids.size() < num_downloads_deleted) 12577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 12587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_COUNTS("Download.DatabaseRemoveDownloadsCountNotRemoved", 12597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ids.size() - num_downloads_deleted); 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryHistory(scoped_refptr<QueryHistoryRequest> request, 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& text_query, 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const QueryOptions& options) { 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text_query.empty()) { 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Basic history query for the main database. 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryHistoryBasic(db_.get(), db_.get(), options, &request->value); 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now query the archived database. This is a bit tricky because we don't 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to query it if the queried time range isn't going to find anything 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in it. 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) bug 1171036: do blimpie querying for the archived database 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as well. 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if (archived_db_.get() && 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expirer_.GetCurrentArchiveTime() - TimeDelta::FromDays(7)) { 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Text history query. 1284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryHistoryText(db_.get(), db_.get(), text_query, options, 1285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &request->value); 1286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (archived_db_.get() && 1287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expirer_.GetCurrentArchiveTime() >= options.begin_time) { 1288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryHistoryText(archived_db_.get(), archived_db_.get(), text_query, 1289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options, &request->value); 1290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), &request->value); 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.QueryHistory", 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic time-based querying of history. 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryHistoryBasic(URLDatabase* url_db, 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitDatabase* visit_db, 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const QueryOptions& options, 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryResults* result) { 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First get all visits. 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 13072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_more_results = visit_db->GetVisibleVisitsInRange(options, &visits); 13082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount()); 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now add them and the URL rows to the results. 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLResult url_result; 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); i++) { 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VisitRow visit = visits[i]; 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a result row for this visit, get the URL info from the DB. 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_db->GetURLRow(visit.url_id, &url_result)) { 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to get id " << visit.url_id 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " from history.urls."; 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // DB out of sync and URL doesn't exist, try to recover. 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_result.url().is_valid()) { 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Got invalid URL from history.urls with id " 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << visit.url_id << ": " 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << url_result.url().possibly_invalid_spec(); 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Don't report invalid URLs in case of corruption. 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The archived database may be out of sync with respect to starring, 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // titles, last visit date, etc. Therefore, we query the main DB if the 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current URL database is not the main one. 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_db == db_.get()) { 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently querying the archived DB, update with the main database to 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // catch any interesting stuff. This will update it if it exists in the 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main DB, and do nothing otherwise. 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetRowForURL(url_result.url(), &url_result); 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_result.set_visit_time(visit.visit_time); 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set whether the visit was blocked for a managed user by looking at the 1342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // transition type. 1343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url_result.set_blocked_visit( 1344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0); 1345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't set any of the query-specific parts of the URLResult, since 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // snippets and stuff don't apply to basic querying. 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->AppendURLBySwapping(&url_result); 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_more_results && options.begin_time <= first_recorded_time_) 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->set_reached_beginning(true); 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Text-based querying of history. 1356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::QueryHistoryText(URLDatabase* url_db, 1357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitDatabase* visit_db, 1358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const string16& text_query, 1359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const QueryOptions& options, 1360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryResults* result) { 1361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLRows text_matches; 1362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_db->GetTextMatches(text_query, &text_matches); 1363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<URLResult> matching_visits; 1365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitVector visits; // Declare outside loop to prevent re-construction. 1366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < text_matches.size(); i++) { 1367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const URLRow& text_match = text_matches[i]; 1368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Get all visits for given URL match. 1369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch visit_db->GetVisitsForURLWithOptions(text_match.id(), options, &visits); 1370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < visits.size(); j++) { 1371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult url_result(text_match); 1372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_result.set_visit_time(visits[j].visit_time); 1373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch matching_visits.push_back(url_result); 1374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::sort(matching_visits.begin(), matching_visits.end(), 1378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch URLResult::CompareVisitTime); 1379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t max_results = options.max_count == 0 ? 1381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::numeric_limits<size_t>::max() : static_cast<int>(options.max_count); 1382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (std::vector<URLResult>::iterator it = matching_visits.begin(); 1383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it != matching_visits.end() && result->size() < max_results; ++it) { 1384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->AppendURLBySwapping(&(*it)); 1385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (matching_visits.size() == result->size() && 1388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch options.begin_time <= first_recorded_time_) 1389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result->set_reached_beginning(true); 1390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Frontend to GetMostRecentRedirectsFrom from the history thread. 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsFrom( 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsFrom(url, &request->value); 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryRedirectsTo( 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryRedirectsRequest> request, 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = GetMostRecentRedirectsTo(url, &request->value); 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), url, success, &request->value); 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetVisibleVisitCountToHost( 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<GetVisibleVisitCountToHostRequest> request, 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time first_visit; 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool success = db_.get() && 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisibleVisitCountToHost(url, &count, &first_visit); 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), success, count, first_visit); 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryTopURLsAndRedirects( 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryTopURLsAndRedirectsRequest> request, 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count) { 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1429b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), false, NULL, NULL); 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<GURL>* top_urls = &request->value.a; 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectMap* redirects = &request->value.b; 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - base::TimeDelta::FromDays(90), 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_urls->push_back(data[i]->GetURL()); 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RefCountedVector<GURL>* list = new RefCountedVector<GURL>; 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(top_urls->back(), &list->data); 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*redirects)[top_urls->back()] = list; 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), true, top_urls, redirects); 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Will replace QueryTopURLsAndRedirectsRequest. 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLs( 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryMostVisitedURLsRequest> request, 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back) { 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1459b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), MostVisitedURLList()); 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result = &request->value; 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryMostVisitedURLsImpl(result_count, days_back, result); 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), *result); 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryFilteredURLs( 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<QueryFilteredURLsRequest> request, 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_count, 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::VisitFilter& filter, 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool extended_info) { 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time request_start = base::Time::Now(); 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1480b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No History Database - return an empty list. 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), FilteredURLList()); 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetDirectVisitsDuringTimes(filter, 0, &visits); 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<URLID, double> score_map; 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score_map[visits[i].url_id] += filter.GetVisitScore(visits[i]); 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(georgey): experiment with visit_segment database granularity (it is 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // currently 24 hours) to use it directly instead of using visits database, 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which is considerably slower. 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.reserve(score_map.size()); 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<URLID, double>::iterator it = score_map.begin(); 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != score_map.end(); ++it) { 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* pud = new PageUsageData(it->first); 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pud->SetScore(it->second); 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.push_back(pud); 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Limit to the top |result_count| results. 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(data.begin(), data.end(), PageUsageData::Predicate); 15082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (result_count && implicit_cast<int>(data.size()) > result_count) 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.resize(result_count); 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow info; 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_->GetURLRow(data[i]->GetID(), &info)) { 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetURL(info.url()); 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i]->SetTitle(info.title()); 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURLList& result = request->value; 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilteredURL url(*current_data); 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extended_info) { 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(current_data->GetID(), &visits); 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.size() > 0) { 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.total_visits = visits.size(); 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < visits.size(); ++i) { 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.duration_opened += 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits[i].visit_duration.InSeconds(); 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits[i].visit_time > url.extended_info.last_visit_time) { 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.extended_info.last_visit_time = visits[i].visit_time; 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(macourteau): implement the url.extended_info.visits stat. 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.push_back(url); 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delta_time = std::max(1, std::min(999, 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>((base::Time::Now() - request_start).InMilliseconds()))); 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATIC_HISTOGRAM_POINTER_BLOCK( 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NewTabPage.SuggestedSitesLoadTime", 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(delta_time), 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LinearHistogram::FactoryGet("NewTabPage.SuggestedSitesLoadTime", 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1000, 100, base::Histogram::kUmaTargetedHistogramFlag)); 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(request->handle(), result); 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::QueryMostVisitedURLsImpl(int result_count, 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int days_back, 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURLList* result) { 1556b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<PageUsageData> data; 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->QuerySegmentUsage(base::Time::Now() - 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromDays(days_back), 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_count, &data.get()); 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); ++i) { 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PageUsageData* current_data = data[i]; 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectList redirects; 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetMostRecentRedirectsFrom(current_data->GetURL(), &redirects); 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MostVisitedURL url = MakeMostVisitedURL(*current_data, redirects); 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->push_back(url); 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsFromSpecificVisit( 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, history::RedirectList* redirects) { 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow any redirects from the given visit and add them to the list. 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It *should* be impossible to get a circular chain here, but we check 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just in case to avoid infinite loops. 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectFromVisit(cur_visit, &cur_visit, &cur_url)) { 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetRedirectsToSpecificVisit( 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit, 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Follow redirects going to cur_visit. These are added to |redirects| in 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the order they are found. If a redirect chain looks like A -> B -> C and 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |cur_visit| = C, redirects will be {B, A} in that order. 1597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL cur_url; 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<VisitID> visit_set; 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (db_->GetRedirectToVisit(cur_visit, &cur_visit, &cur_url)) { 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_set.find(cur_visit) != visit_set.end()) { 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Loop in visit chain, giving up"; 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit_set.insert(cur_visit); 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->push_back(cur_url); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsFrom( 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& from_url, 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1617b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID from_url_id = db_->GetRowForURL(from_url, NULL); 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(from_url_id, NULL); 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsFromSpecificVisit(cur_visit, redirects); 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetMostRecentRedirectsTo( 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& to_url, 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirects) { 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirects->clear(); 1633b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLID to_url_id = db_->GetRowForURL(to_url, NULL); 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID cur_visit = db_->GetMostRecentVisitForURL(to_url_id, NULL); 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cur_visit) 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No visits for URL. 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRedirectsToSpecificVisit(cur_visit, redirects); 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleAutocomplete(HistoryURLProvider* provider, 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryURLProviderParams* params) { 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExecuteWithDB should handle the NULL database case. 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) provider->ExecuteWithDB(this, db_.get(), params); 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1651bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid HistoryBackend::DeleteFTSIndexDatabases() { 1652bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Find files on disk matching the text databases file pattern so we can 1653bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // quickly test for and delete them. 1654bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath::StringType filepattern = 1655bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch FILE_PATH_LITERAL("History Index *"); 1656bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FileEnumerator enumerator( 1657bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch history_dir_, false, base::FileEnumerator::FILES, filepattern); 1658bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch int num_databases_deleted = 0; 1659bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::FilePath current_file; 1660bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch while (!(current_file = enumerator.Next()).empty()) { 1661bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (sql::Connection::Delete(current_file)) 1662bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted++; 1663bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 1664bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch UMA_HISTOGRAM_COUNTS("History.DeleteFTSIndexDatabases", 1665bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch num_databases_deleted); 1666bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 1667bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFavicons( 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 16722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 167390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 16742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(NULL, icon_urls, icon_types, 16752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 16762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetFaviconsForURL( 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 16832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 168490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 16852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(bitmap_results); 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconsFromDB(page_url, icon_types, desired_size_in_dip, 16872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::GetFaviconForID( 169190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID favicon_id, 16922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int desired_size_in_dip, 16932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ScaleFactor desired_scale_factor, 169490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 169590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> favicon_ids; 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ui::ScaleFactor> desired_scale_factors; 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors.push_back(desired_scale_factor); 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get results from DB. 17012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, 17022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, 17032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, 17042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetch( 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 17122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 171390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 17142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateFaviconMappingsAndFetchImpl(&page_url, icon_urls, icon_types, 17152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, 17162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results); 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::MergeFavicon( 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 17212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 172290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type, 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedMemory> bitmap_data, 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& pixel_size) { 1725b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID favicon_id = 172990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!favicon_id) { 17322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There is no favicon at |icon_url|, create it. 1733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch favicon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 17342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 17372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(favicon_id, &bitmap_id_sizes); 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is already a favicon bitmap of |pixel_size| at |icon_url|, 17402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // replace it. 17412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool bitmap_identical = false; 17422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool replaced_bitmap = false; 17432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 17442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes[i].pixel_size == pixel_size) { 17452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsFaviconBitmapDataEqual(bitmap_id_sizes[i].bitmap_id, bitmap_data)) { 17462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 17472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id_sizes[i].bitmap_id, base::Time::Now()); 17482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_identical = true; 17492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 17502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id_sizes[i].bitmap_id, 17512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_data, base::Time::Now()); 17522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) replaced_bitmap = true; 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a vector of the pixel sizes of the favicon bitmaps currently at 17592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url|. 17602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size> favicon_sizes; 17612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) 17622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmap_id_sizes[i].pixel_size); 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!replaced_bitmap && !bitmap_identical) { 17652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set the preexisting favicon bitmaps as expired as the preexisting favicon 17662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmaps are not consistent with the merged in data. 17672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(favicon_id); 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete an arbitrary favicon bitmap to avoid going over the limit of 17702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |kMaxFaviconBitmapsPerIconURL|. 17712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bitmap_id_sizes.size() >= kMaxFaviconBitmapsPerIconURL) { 17722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[0].bitmap_id); 17732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.erase(favicon_sizes.begin()); 17742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 17752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, bitmap_data, base::Time::Now(), 17762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pixel_size); 17772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(pixel_size); 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A site may have changed the favicons that it uses for |page_url|. 17812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Example Scenario: 17822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // page_url = news.google.com 178358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Initial State: www.google.com/favicon.ico 16x16, 32x32 17842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // MergeFavicon(news.google.com, news.google.com/news_specific.ico, ..., 17852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ..., 16x16) 17862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 17872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulties: 17882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1. Sync requires that a call to GetFaviconsForURL() returns the 17892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |bitmap_data| passed into MergeFavicon(). 17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - It is invalid for the 16x16 bitmap for www.google.com/favicon.ico to 17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stay mapped to news.google.com because it would be unclear which 16x16 17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap should be returned via GetFaviconsForURL(). 17932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2. www.google.com/favicon.ico may be mapped to more than just 17952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com (eg www.google.com). 17962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - The 16x16 bitmap cannot be deleted from www.google.com/favicon.ico 17972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 17982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // To resolve these problems, we copy all of the favicon bitmaps previously 17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // mapped to news.google.com (|page_url|) and add them to the favicon at 18002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com/news_specific.ico (|icon_url|). The favicon sizes for 18012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |icon_url| are set to default to indicate that |icon_url| has incomplete 18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // / incorrect data. 180358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Difficulty 1: All but news.google.com/news_specific.ico are unmapped from 18042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // news.google.com 18052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Difficulty 2: The favicon bitmaps for www.google.com/favicon.ico are not 18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // modified. 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<IconMapping> icon_mappings; 18092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_type, &icon_mappings); 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy the favicon bitmaps mapped to |page_url| to the favicon at |icon_url| 18122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // till the limit of |kMaxFaviconBitmapsPerIconURL| is reached. 18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) { 18142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 18152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings[i].icon_url == icon_url) 18182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<FaviconBitmap> bitmaps_to_copy; 18212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmaps(icon_mappings[i].icon_id, 18222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &bitmaps_to_copy); 18232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t j = 0; j < bitmaps_to_copy.size(); ++j) { 18242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do not add a favicon bitmap at a pixel size for which there is already 18252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a favicon bitmap mapped to |icon_url|. The one there is more correct 18262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and having multiple equally sized favicon bitmaps for |page_url| is 18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ambiguous in terms of GetFaviconsForURL(). 18282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size>::iterator it = std::find(favicon_sizes.begin(), 18292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.end(), bitmaps_to_copy[j].pixel_size); 18302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != favicon_sizes.end()) 18312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 18322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add the favicon bitmap as expired as it is not consistent with the 18342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // merged in data. 18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(favicon_id, 18362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].bitmap_data, base::Time(), 18372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmaps_to_copy[j].pixel_size); 18382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_sizes.push_back(bitmaps_to_copy[j].pixel_size); 18392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_sizes.size() >= kMaxFaviconBitmapsPerIconURL) 18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update the favicon mappings such that only |icon_url| is mapped to 18462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |page_url|. 18472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool mapping_changed = false; 18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (icon_mappings.size() != 1 || icon_mappings[0].icon_url != icon_url) { 184990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> favicon_ids; 18502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_ids.push_back(favicon_id); 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, favicon_ids); 18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mapping_changed = true; 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mapping_changed || !bitmap_identical) 18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFavicons( 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 186290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type, 186390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconBitmapData>& favicon_bitmap_data) { 1864b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || !db_) 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(ValidateSetFaviconsParams(favicon_bitmap_data)); 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build map of FaviconBitmapData for each icon url. 187090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) typedef std::map<GURL, std::vector<chrome::FaviconBitmapData> > 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL; 18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BitmapDataByIconURL grouped_by_icon_url; 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) grouped_by_icon_url[icon_url].push_back(favicon_bitmap_data[i]); 18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Track whether the method modifies or creates any favicon bitmaps, favicons 18792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // or icon mappings. 18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool data_modified = false; 18812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 188290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> icon_ids; 18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapDataByIconURL::const_iterator it = grouped_by_icon_url.begin(); 18842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != grouped_by_icon_url.end(); ++it) { 18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = it->first; 188690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID icon_id = 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); 18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!icon_id) { 18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(pkotwicz): Remove the favicon sizes attribute from 18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ThumbnailDatabase::AddFavicon(). 1892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type); 18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified = true; 18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_ids.push_back(icon_id); 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data_modified) 18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, &data_modified); 18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconBitmaps(icon_id, it->second, NULL); 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_modified |= 19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids); 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data_modified) { 19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Send notification to the UI as an icon mapping, favicon, or favicon 19082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bitmap was changed by this function. 19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(page_url); 19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) { 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1917b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_ || 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !thumbnail_db_->GetIconMappingsForPageURL(page_url, 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings)) 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->SetFaviconOutOfDate(m->icon_id); 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CloneFavicons(const GURL& old_page_url, 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& new_page_url) { 1931b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevent cross-domain cloning. 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetImportedFavicons( 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ImportedFaviconUsage>& favicon_usage) { 1944b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time now = Time::Now(); 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Track all URLs that had their favicons set or updated. 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<GURL> favicons_changed; 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_usage.size(); i++) { 195390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL( 195490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) favicon_usage[i].favicon_url, chrome::FAVICON, NULL); 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicon_id) { 19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This favicon doesn't exist yet, so we create it using the given data. 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Pass in real pixel size. 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_id = thumbnail_db_->AddFavicon( 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_usage[i].favicon_url, 196090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FAVICON, 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new base::RefCountedBytes(favicon_usage[i].png_data), 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now, 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size()); 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the mapping from all the URLs to the favicon. 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service = GetBookmarkService(); 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator url = favicon_usage[i].urls.begin(); 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url != favicon_usage[i].urls.end(); ++url) { 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*url, &url_row)) { 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL is present as a bookmark, add the url in history to 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save the favicon mapping. This will match with what history db does 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for regular bookmarked URLs with favicons - when history db is 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cleaned, we keep an entry in the db with 0 visits as long as that 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // url is bookmarked. 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service && bookmark_service_->IsBookmarked(*url)) { 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_info(*url); 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_visit_count(0); 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_typed_count(0); 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_last_visit(base::Time()); 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_info.set_hidden(false); 19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->AddURL(url_info); 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 198890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!thumbnail_db_->GetIconMappingsForPageURL( 198990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *url, chrome::FAVICON, NULL)) { 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL is present in history, update the favicon *only* if it is not 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set already. 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(*url, favicon_id); 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicons_changed.insert(*url); 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!favicons_changed.empty()) { 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the notification about the changed favicon URLs. 200190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FaviconChangedDetails* changed_details = new FaviconChangedDetails; 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.swap(favicons_changed); 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details); 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::UpdateFaviconMappingsAndFetchImpl( 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL* page_url, 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<GURL>& icon_urls, 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 20132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 201490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* bitmap_results) { 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |page_url| is specified, |icon_types| must be either a single icon 20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // type or icon types which are equivalent. 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!page_url || 201890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_types == chrome::FAVICON || 201990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_types == chrome::TOUCH_ICON || 202090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_types == chrome::TOUCH_PRECOMPOSED_ICON || 202190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_types == (chrome::TOUCH_ICON | chrome::TOUCH_PRECOMPOSED_ICON)); 20222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_results->clear(); 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2024b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> favicon_ids; 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The icon type for which the mappings will the updated and data will be 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned. 203290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType selected_icon_type = chrome::INVALID_ICON; 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_urls.size(); ++i) { 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& icon_url = icon_urls[i]; 203690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type_out; 203790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const chrome::FaviconID favicon_id = 203890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) thumbnail_db_->GetFaviconIDForFaviconURL( 203990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) icon_url, icon_types, &icon_type_out); 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (favicon_id) { 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return and update icon mappings only for the largest icon type. As 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |icon_urls| is not sorted in terms of icon type, clear |favicon_ids| 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if an |icon_url| with a larger icon type is found. 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out > selected_icon_type) { 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_icon_type = icon_type_out; 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.clear(); 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_type_out == selected_icon_type) 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(favicon_id); 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_url && !favicon_ids.empty()) { 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_updated = 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetFaviconMappingsForPageAndRedirects(*page_url, selected_icon_type, 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids); 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mappings_updated) { 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendFaviconChangedNotificationForPageAndRedirects(*page_url); 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleCommit(); 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip, 20652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_scale_factors, bitmap_results); 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SetFaviconBitmaps( 206990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID icon_id, 207090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconBitmapData>& favicon_bitmap_data, 20712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* favicon_bitmaps_changed) { 20722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 20732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = false; 20742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes); 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 207890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapData> to_add = favicon_bitmap_data; 20792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { 20812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& pixel_size = bitmap_id_sizes[i].pixel_size; 208290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapData>::iterator match_it = to_add.end(); 208390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (std::vector<chrome::FaviconBitmapData>::iterator it = to_add.begin(); 20842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != to_add.end(); ++it) { 20852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->pixel_size == pixel_size) { 20862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) match_it = it; 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id = bitmap_id_sizes[i].bitmap_id; 20922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (match_it == to_add.end()) { 20932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->DeleteFaviconBitmap(bitmap_id); 20942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 20962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 20982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed && 20992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !*favicon_bitmaps_changed && 21002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsFaviconBitmapDataEqual(bitmap_id, match_it->bitmap_data)) { 21012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmapLastUpdateTime( 21022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bitmap_id, base::Time::Now()); 21032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 21042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->SetFaviconBitmap(bitmap_id, match_it->bitmap_data, 21052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now()); 21062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 21092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 21102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) to_add.erase(match_it); 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < to_add.size(); ++i) { 21152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->AddFaviconBitmap(icon_id, to_add[i].bitmap_data, 21162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time::Now(), to_add[i].pixel_size); 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_bitmaps_changed) 21192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *favicon_bitmaps_changed = true; 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistoryBackend::ValidateSetFaviconsParams( 212490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconBitmapData>& favicon_bitmap_data) const { 21252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::map<GURL, size_t> BitmapsPerIconURL; 21262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BitmapsPerIconURL num_bitmaps_per_icon_url; 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { 2128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!favicon_bitmap_data[i].bitmap_data.get()) 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url = favicon_bitmap_data[i].icon_url; 21322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!num_bitmaps_per_icon_url.count(icon_url)) 21332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_bitmaps_per_icon_url[icon_url] = 1u; 21342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 21352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++num_bitmaps_per_icon_url[icon_url]; 21362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 21372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 21382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (num_bitmaps_per_icon_url.size() > kMaxFaviconsPerPage) 21392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BitmapsPerIconURL::const_iterator it = num_bitmaps_per_icon_url.begin(); 21422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != num_bitmaps_per_icon_url.end(); ++it) { 21432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->second > kMaxFaviconBitmapsPerIconURL) 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HistoryBackend::IsFaviconBitmapDataEqual( 21502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconBitmapID bitmap_id, 21512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<base::RefCountedMemory>& new_bitmap_data) { 2152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!new_bitmap_data.get()) 21532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<base::RefCountedMemory> original_bitmap_data; 21562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) thumbnail_db_->GetFaviconBitmap(bitmap_id, 21572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 21582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &original_bitmap_data, 21592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL); 21602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_bitmap_data->Equals(original_bitmap_data); 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconsFromDB( 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_types, 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 216890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* favicon_bitmap_results) { 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(favicon_bitmap_results); 21702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_bitmap_results->clear(); 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_ || !thumbnail_db_) 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Time the query. 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks beginning_time = TimeTicks::Now(); 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get FaviconIDs for |page_url| and one of |icon_types|. 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types, 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &icon_mappings); 218290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> favicon_ids; 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < icon_mappings.size(); ++i) 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_ids.push_back(icon_mappings[i].icon_id); 21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populate |favicon_bitmap_results| and |icon_url_sizes|. 21872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = GetFaviconBitmapResultsForBestMatch(favicon_ids, 21882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_size_in_dip, desired_scale_factors, favicon_bitmap_results); 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name 21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks::Now() - beginning_time); 21912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return success && !favicon_bitmap_results->empty(); 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::GetFaviconBitmapResultsForBestMatch( 219590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconID>& candidate_favicon_ids, 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desired_size_in_dip, 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<ui::ScaleFactor>& desired_scale_factors, 219890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconBitmapResult>* favicon_bitmap_results) { 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->clear(); 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate_favicon_ids.empty()) 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the FaviconID and the FaviconBitmapIDs which best match 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |desired_size_in_dip| and |desired_scale_factors|. 22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkotwicz): Select bitmap results from multiple favicons once 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content::FaviconStatus supports multiple icon URLs. 220890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconID best_favicon_id = 0; 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapID> best_bitmap_ids; 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float highest_score = kSelectFaviconFramesInvalidScore; 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < candidate_favicon_ids.size(); ++i) { 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FaviconBitmapIDSize> bitmap_id_sizes; 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetFaviconBitmapIDSizes(candidate_favicon_ids[i], 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_id_sizes); 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Build vector of gfx::Size from |bitmap_id_sizes|. 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<gfx::Size> sizes; 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < bitmap_id_sizes.size(); ++j) 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizes.push_back(bitmap_id_sizes[j].pixel_size); 22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<size_t> candidate_bitmap_indices; 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score = 0; 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFaviconFrameIndices(sizes, 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_scale_factors, 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_size_in_dip, 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &candidate_bitmap_indices, 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &score); 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (score > highest_score) { 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) highest_score = score; 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_favicon_id = candidate_favicon_ids[i], 22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.clear(); 22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < candidate_bitmap_indices.size(); ++j) { 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t candidate_index = candidate_bitmap_indices[j]; 22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_bitmap_ids.push_back( 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_id_sizes[candidate_index].bitmap_id); 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct FaviconBitmapResults from |best_favicon_id| and 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |best_bitmap_ids|. 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL icon_url; 224390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type; 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url, 2245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &icon_type)) { 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < best_bitmap_ids.size(); ++i) { 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_updated; 225190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::FaviconBitmapResult bitmap_result; 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_url = icon_url; 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.icon_type = icon_type; 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->GetFaviconBitmap(best_bitmap_ids[i], 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &last_updated, 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.bitmap_data, 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bitmap_result.pixel_size)) { 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap_result.expired = (Time::Now() - last_updated) > 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromDays(kFaviconRefetchDays); 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap_result.is_valid()) 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_bitmap_results->push_back(bitmap_result); 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPageAndRedirects( 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 227190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type, 227290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconID>& icon_ids) { 2273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find all the pages whose favicons we should set, we want to set it for 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all the pages in the redirect chain if it redirected. 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirects; 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirects); 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save page <-> favicon associations. 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (history::RedirectList::const_iterator i(redirects.begin()); 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != redirects.end(); ++i) { 22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed |= SetFaviconMappingsForPage(*i, icon_type, icon_ids); 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::SetFaviconMappingsForPage( 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 229390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) chrome::IconType icon_type, 229490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<chrome::FaviconID>& icon_ids) { 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(icon_ids.size(), kMaxFaviconsPerPage); 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool mappings_changed = false; 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Two icon types are considered 'equivalent' if one of the icon types is 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TOUCH_ICON and the other is TOUCH_PRECOMPOSED_ICON. 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the icon mappings from |page_url| for |icon_type| to the favicons 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with |icon_ids|. Mappings for |page_url| to favicons of type |icon_type| 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whose FaviconID is not in |icon_ids| are removed. All icon mappings for 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |page_url| to favicons of a type equivalent to |icon_type| are removed. 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any favicons which are orphaned as a result of the removal of the 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon mappings. 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 230890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID> unmapped_icon_ids = icon_ids; 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<IconMapping> icon_mappings; 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings); 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m != icon_mappings.end(); ++m) { 231590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<chrome::FaviconID>::iterator icon_id_it = std::find( 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.begin(), unmapped_icon_ids.end(), m->icon_id); 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the icon mapping already exists, avoid removing it and adding it back. 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_id_it != unmapped_icon_ids.end()) { 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmapped_icon_ids.erase(icon_id_it); 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 232490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if ((icon_type == chrome::TOUCH_ICON && 232590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) m->icon_type == chrome::TOUCH_PRECOMPOSED_ICON) || 232690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (icon_type == chrome::TOUCH_PRECOMPOSED_ICON && 232790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) m->icon_type == chrome::TOUCH_ICON) || (icon_type == m->icon_type)) { 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteIconMapping(m->mapping_id); 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removing the icon mapping may have orphaned the associated favicon so 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we must recheck it. This is not super fast, but this case will get 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // triggered rarely, since normally a page will always map to the same 23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon IDs. It will mostly happen for favicons we import. 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!thumbnail_db_->HasMappingFor(m->icon_id)) 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->DeleteFavicon(m->icon_id); 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < unmapped_icon_ids.size(); ++i) { 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->AddIconMapping(page_url, unmapped_icon_ids[i]); 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mappings_changed = true; 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mappings_changed; 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::GetCachedRecentRedirects( 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url, 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList* redirect_list) { 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RedirectCache::iterator iter = recent_redirects_.Get(page_url); 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != recent_redirects_.end()) { 23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *redirect_list = iter->second; 23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The redirect chain should have the destination URL as the last item. 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!redirect_list->empty()); 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(redirect_list->back() == page_url); 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No known redirects, construct mock redirect chain containing |page_url|. 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) redirect_list->push_back(page_url); 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::SendFaviconChangedNotificationForPageAndRedirects( 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& page_url) { 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::RedirectList redirect_list; 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetCachedRecentRedirects(page_url, &redirect_list); 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 236890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FaviconChangedDetails* changed_details = new FaviconChangedDetails; 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < redirect_list.size(); ++i) 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details->urls.insert(redirect_list[i]); 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changed_details); 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::Commit() { 2377b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that a commit may not actually have been scheduled if a caller 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // explicitly calls this instead of using ScheduleCommit. Likewise, we 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may reset the flag written by a pending commit. But this is OK! It 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will merely cause extra commits (which is kind of the idea). We 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // could optimize more for this case (we may get two extra commits in 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some cases) but it hasn't been important yet. 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelScheduledCommit(); 23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2392b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (thumbnail_db_) { 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 0) << 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Somebody left a transaction open"; 23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2399b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->CommitTransaction(); 24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ScheduleCommit() { 2406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) 24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = new CommitLaterTask(this); 240990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()), 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); 24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::CancelScheduledCommit() { 2416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scheduled_commit_.get()) { 24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_->Cancel(); 24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheduled_commit_ = NULL; 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTaskImpl() { 2423b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) { 24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // db went away, release all the refs. 24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseDBTasks(); 24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any canceled tasks. 24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!db_task_requests_.empty() && db_task_requests_.front()->canceled()) { 24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.front()->Release(); 24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (db_task_requests_.empty()) 24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the first task. 24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDBTaskRequest* request = db_task_requests_.front(); 24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.pop_front(); 24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->value->RunOnDBThread(this, db_.get())) { 24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The task is done. Notify the callback. 24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->ForwardResult(); 24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We AddRef'd the request before adding, need to release it now. 24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->Release(); 24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tasks wants to run some more. Schedule it at the end of current tasks. 24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request); 24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And process it after an invoke later. 244990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&HistoryBackend::ProcessDBTaskImpl, this)); 24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ReleaseDBTasks() { 24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::list<HistoryDBTaskRequest*>::iterator i = 24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.begin(); i != db_task_requests_.end(); ++i) { 24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->Release(); 24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.clear(); 24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generic operations 24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { 24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURLs(urls); 24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteURL(const GURL& url) { 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(url); 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, we 24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to get it on disk ASAP. 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Commit(); 24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ExpireHistoryBetween( 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<GURL>& restrict_urls, 24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time begin_time, 24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Time end_time) { 249058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!db_) 249158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 249358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (begin_time.is_null() && (end_time.is_null() || end_time.is_max()) && 249458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) restrict_urls.empty()) { 249558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Special case deleting all history so it can be faster and to reduce the 249658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // possibility of an information leak. 249758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DeleteAllHistory(); 249858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 249958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Clearing parts of history, have the expirer do the depend 250058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expirer_.ExpireHistoryBetween(restrict_urls, begin_time, end_time); 250158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 250258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Force a commit, if the user is deleting something for privacy reasons, 250358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // we want to get it on disk ASAP. 250458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Commit(); 25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (begin_time <= first_recorded_time_) 25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 25102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistoryForTimes( 25122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::set<base::Time>& times, 25132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time begin_time, base::Time end_time) { 2514b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (times.empty() || !db_) 25152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 25162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.begin() >= begin_time) 25182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Min time is before begin time: " 25192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime(); 25202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(*times.rbegin() < end_time) 25212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Max time is after end time: " 25222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime(); 25232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history::QueryOptions options; 25252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.begin_time = begin_time; 25262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.end_time = end_time; 25272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES; 25282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryResults results; 25292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueryHistoryBasic(db_.get(), db_.get(), options, &results); 25302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1st pass: find URLs that are visited at one of |times|. 25322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<GURL> urls; 25332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 25342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times.count(results[i].visit_time()) > 0) 25352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) urls.insert(results[i].url()); 25362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.empty()) 25382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 25392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2nd pass: collect all visit times of those URLs. 25412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::Time> times_to_expire; 25422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 25432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (urls.count(results[i].url())) 25442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.push_back(results[i].visit_time()); 25452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put the times in reverse chronological order and remove 25482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // duplicates (for expirer_.ExpireHistoryForTimes()). 25492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::sort(times_to_expire.begin(), times_to_expire.end(), 25502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::greater<base::Time>()); 25512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.erase( 25522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::unique(times_to_expire.begin(), times_to_expire.end()), 25532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) times_to_expire.end()); 25542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Expires by times and commit. 25562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!times_to_expire.empty()); 25572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryForTimes(times_to_expire); 25582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 25592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(times_to_expire.back() >= first_recorded_time_); 25612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if we expired it. 25622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (times_to_expire.back() == first_recorded_time_) 25632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HistoryBackend::ExpireHistory( 25672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<history::ExpireHistoryArgs>& expire_list) { 2568b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (db_) { 25692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool update_first_recorded_time = false; 25702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<history::ExpireHistoryArgs>::const_iterator it = 25722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expire_list.begin(); it != expire_list.end(); ++it) { 25732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expirer_.ExpireHistoryBetween(it->urls, it->begin_time, it->end_time); 25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->begin_time < first_recorded_time_) 25762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) update_first_recorded_time = true; 25772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Commit(); 25792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update |first_recorded_time_| if any deletion might have affected it. 25812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (update_first_recorded_time) 25822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 25832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) { 2587b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<GURL>::const_iterator i = urls.begin(); i != urls.end(); ++i) { 25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow url_row; 25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(*i, &url_row)) 25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // The URL isn't in the db; nothing to do. 25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector visits; 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetVisitsForURL(url_row.id(), &visits); 25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visits.empty()) 25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expirer_.DeleteURL(*i); // There are no more visits; nuke the URL. 26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void HistoryBackend::DatabaseErrorCallback(int error, sql::Statement* stmt) { 26047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!scheduled_kill_db_ && sql::IsErrorCatastrophic(error)) { 26057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = true; 26067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Don't just do the close/delete here, as we are being called by |db| and 26077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // that seems dangerous. 26087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // TODO(shess): Consider changing KillHistoryDatabase() to use 26097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // RazeAndClose(). Then it can be cleared immediately. 26107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::MessageLoop::current()->PostTask( 26117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) FROM_HERE, 26127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&HistoryBackend::KillHistoryDatabase, this)); 26137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 26147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 26157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::KillHistoryDatabase() { 26177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scheduled_kill_db_ = false; 2618b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!db_) 26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rollback transaction because Raze() cannot be called from within a 26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction. 26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RollbackTransaction(); 26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = db_->Raze(); 26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success); 26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release AndroidProviderBackend before other objects. 26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) android_provider_backend_.reset(); 26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The expirer keeps tabs on the active databases. Tell it about the 26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // databases which will be closed. 2634bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch expirer_.SetDatabases(NULL, NULL, NULL); 26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). 26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseAllDatabases(); 26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::ProcessDBTask( 26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HistoryDBTaskRequest> request) { 2643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(request.get()); 26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request->canceled()) 26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool task_scheduled = !db_task_requests_.empty(); 26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we up the refcount of the request. ProcessDBTaskImpl will 26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // release when done with the task. 26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->AddRef(); 26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_task_requests_.push_back(request.get()); 26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!task_scheduled) { 26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No other tasks are scheduled. Process request now. 26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDBTaskImpl(); 26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::BroadcastNotifications( 26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryDetails* details_deleted) { 26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |delegate_| may be NULL if |this| is in the process of closing (closed by 2662b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // HistoryService -> HistoryBackend::Closing(). 2663b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->BroadcastNotifications(type, details_deleted); 26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete details_deleted; 26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2669b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void HistoryBackend::NotifySyncURLsDeleted(bool all_history, 2670b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool archived, 2671b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) URLRows* rows) { 2672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (typed_url_syncable_service_.get()) 2673b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typed_url_syncable_service_->OnUrlsDeleted(all_history, archived, rows); 2674b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 2675b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Deleting -------------------------------------------------------------------- 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::DeleteAllHistory() { 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our approach to deleting all history is: 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Copy the bookmarks and their dependencies to new tables with temporary 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // names. 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. Delete the original tables. Since tables can not share pages, we know 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that any data we don't want to keep is now in an unused page. 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3. Renaming the temporary tables to match the original. 26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4. Vacuuming the database to delete the unused pages. 26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we are likely to have very few bookmarks and their dependencies 26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compared to all history, this is also much faster than just deleting from 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the original tables directly. 26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the bookmarked URLs. 26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<BookmarkService::URLAndTitle> starred_urls; 26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkService* bookmark_service = GetBookmarkService(); 26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service) 26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_->GetBookmarks(&starred_urls); 26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRows kept_urls; 26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < starred_urls.size(); i++) { 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRow row; 27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->GetRowForURL(starred_urls[i].url, &row)) 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear the last visit time so when we write these rows they are "clean." 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_last_visit(Time()); 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_visit_count(0); 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row.set_typed_count(0); 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.push_back(row); 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear thumbnail and favicon history. The favicons for the given URLs will 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be kept. 27123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!ClearAllThumbnailHistory(kept_urls)) { 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Thumbnail history could not be cleared"; 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We continue in this error case. If the user wants to delete their 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // history, we should delete as much as we can. 27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 271858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // ClearAllMainHistory will change the IDs of the URLs in kept_urls. 271958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Therefore, we clear the list afterwards to make sure nobody uses this 272058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // invalid data. 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ClearAllMainHistory(kept_urls)) 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Main history could not be cleared"; 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kept_urls.clear(); 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Delete archived history. 2726b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (archived_db_) { 27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close the database and delete the file. 27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 27292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath archived_file_name = GetArchivedFileName(); 2730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(archived_file_name); 27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now re-initialize the database (which may fail). 27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(new ArchivedDatabase()); 27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!archived_db_->Init(archived_file_name)) { 27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Could not initialize the archived database."; 27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_.reset(); 27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open our long-running transaction on this database. 27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) archived_db_->BeginTransaction(); 27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 274558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Send out the notification that history is cleared. The in-memory database 27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will pick this up and clear itself. 27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLsDeletedDetails* details = new URLsDeletedDetails; 27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details->all_history = true; 2749b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NotifySyncURLsDeleted(true, false, NULL); 27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, details); 27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool HistoryBackend::ClearAllThumbnailHistory(const URLRows& kept_urls) { 2754b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!thumbnail_db_) { 27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we have no reference to the thumbnail database, maybe there was an 27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error opening it. In this case, we just try to blow it away to try to 27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fix the error if it exists. This may fail, in which case either the 27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file doesn't exist or there's no more we can do. 27593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sql::Connection::Delete(GetFaviconsFileName()); 27603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 27613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Older version of the database. 2762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(GetThumbnailFileName()); 27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Urls to retain mappings for. 27673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<GURL> urls_to_keep; 27683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); 27693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) i != kept_urls.end(); ++i) { 27703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) urls_to_keep.push_back(i->url()); 27713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Isolate from any long-running transaction. 27743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 27753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(shess): If this fails, perhaps the database should be razed 27783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // or deleted. 27793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!thumbnail_db_->RetainDataForPageUrls(urls_to_keep)) { 27803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->RollbackTransaction(); 27813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 27823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO (michaelbai): Add the unit test once AndroidProviderBackend is 27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avaliable in HistoryBackend. 27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->ClearAndroidURLRows(); 27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to remove all the pages associated with the dropped tables. There 27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must be no transaction open on the table when we do this. We assume that 27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our long-running transaction is open, so we complete it and start it again. 27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(thumbnail_db_->transaction_nesting() == 1); 27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->CommitTransaction(); 27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->Vacuum(); 27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail_db_->BeginTransaction(); 27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HistoryBackend::ClearAllMainHistory(const URLRows& kept_urls) { 28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the duplicate URL table. We will copy the kept URLs into this. 28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CreateTemporaryURLTable()) 28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 280658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Insert the URLs into the temporary table. 28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (URLRows::const_iterator i = kept_urls.begin(); i != kept_urls.end(); 28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 280958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) db_->AddTemporaryURL(*i); 28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the original URL table with the temporary one. 28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->CommitTemporaryURLTable()) 28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the old tables and recreate them empty. 28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->RecreateAllTablesButURL(); 28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vacuum to reclaim the space from the dropped tables. This must be done 28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when there is no transaction open, and we assume that our long-running 28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction is currently open. 28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->CommitTransaction(); 28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->Vacuum(); 28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->BeginTransaction(); 28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetStartDate(&first_recorded_time_); 28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkService* HistoryBackend::GetBookmarkService() { 28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bookmark_service_) 28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_service_->BlockTillLoaded(); 28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bookmark_service_; 28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { 28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BriefVisitInfo info; 28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.url_id = visit.url_id; 28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.time = visit.visit_time; 28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.transition = visit.transition; 28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have a delegate yet during setup or shutdown, we will drop 28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // these notifications. 2843b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (delegate_) 28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->NotifyVisitDBObserversOnAddVisit(info); 28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID) 2848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::PopulateMostVisitedURLMap() { 2849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MostVisitedURLList most_visited_urls; 2850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch QueryMostVisitedURLsImpl(kPageVisitStatsMaxTopSites, kSegmentDataRetention, 2851eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &most_visited_urls); 2852eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_LE(most_visited_urls.size(), kPageVisitStatsMaxTopSites); 2854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < most_visited_urls.size(); ++i) { 2855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].url] = i; 2856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t j = 0; j < most_visited_urls[i].redirects.size(); ++j) 2857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch most_visited_urls_map_[most_visited_urls[i].redirects[j]] = i; 2858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HistoryBackend::RecordTopPageVisitStats(const GURL& url) { 2862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int rank = kPageVisitStatsMaxTopSites; 2863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); 2864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it != most_visited_urls_map_.end()) 2865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank = (*it).second; 2866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", 2867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rank, kPageVisitStatsMaxTopSites + 1); 2868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 2870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 2872